Archive for the ‘ perl ’ Category

在perl中Crypt::Blowfish加解密的例子:

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/perl
 
use strict;
use warnings;
 
use Crypt::Blowfish;
 
my $key = '123456';
my $content = 'i love you selina!';
 
 
if (length($key) % 8 != 0) {
    $key .= "\000"x(8 - length($key) % 8); 
}
 
my $ci = new Crypt::Blowfish $key;
 
### encrypt:
my $plain = $content;
my $encryp;
while(my $p = substr($plain, 0, 8)) {
    my $len = length($p);
    if ($len % 8 != 0) {
        $p .= "\000"x( 8 - $len % 8); 
    }   
    $encryp .= $ci->encrypt($p);
    if (length($plain) > 8) {
        $plain = substr($plain, 8)  
    } else {
        last;
    }   
}
 
### decrypt:
my $decryp;
$plain = $encryp;
while(my $p = substr($plain, 0, 8)) {
    my $len = length($p);
    if ($len % 8 != 0) {
        $p .= "\000"x( 8 - $len % 8); 
    }   
    $decryp .= $ci->decrypt($p);
    if (length($plain) > 8) {
        $plain = substr($plain, 8)  
    } else {
        last;
    }   
}
 
print "encrypt: ", unpack("H*", $encryp), "\n";
print "decrypt: ", unpack("H*", $decryp), "\n";
print "decrypt: ($decryp)\n";

输出如下:

encrypt: f387ab6368b07639ed9adf97b2527fac6af3c55dd58bdce2
decrypt: 69206c6f766520796f752073656c696e6121000000000000
decrypt: (i love you selina!)

在perl的maillist看到一封大牛(cnhacktnt)解释编码的mail,, perl字节流和字符流, 说的非常清晰, 也加深了自己对perl字符编码的理解. share一下.

需要分清楚“字符(character)”和“字节流(Octet stream)”的概念,你的perl程序所取到的输入,以及它对外的输出(就像你用print打印)都是字节流,字节流是没有语义的,对perl来说它就是一堆字节,没有额外的意义。
而字符串和字节流是不同的,字符串有语义,它代表某个或某些个字符,直白来说,我们看到的“abcd1234“等等都是字符。而字节流可以用来表示字符串,同一个字符串,它对应的字节流可以不同,为什么呢?因为同一个字符串可以用不同的编码方式(如utf8或gb2312)来编码,编码过后得到的,便是相对应的字节流。
在perl中,你输入的一个字符串是以字节流的形式传递给perl的,如果你想perl把你输入的字符串真正当成字符串来理解和操作,你需要告诉perl这串字符的编码是什么,比如(我的环境为utf8):

use Encode;
$string=”中国”;
$string_decoded=decode_utf8($string);

此时,$string 对perl来说只是用utf8编码过的字节流(十六进制为\xE4\xB8\xAD\xE5\x9B\xBD),这个时候,perl只会按字节来对他操作,因为perl不知道它是啥东西。
而 $string_decoded 对perl来说就是有语义的字符串了,虽然他本身在perl内部是以UTF8编码的方式存储的,但是它已经被打上了标记,perl知道它是字符串,该按字符来操作,此时如果你用substr之类的函数对 $string_decoded 操作的话,便是按 “中(\xE4\xB8\xAD)”,“国(\xE5\x9B\xBD)” 两个字符来操作了,而不是在未 decode 之前,以一个字节一个字节的方式处理。

在输出的时候,我们应该仍以字节流的方式输出,因为字符只是一个概念,一个具象,它可以有不同的表现形式(不同编码的字节流),这个时候你可以根据下一个需要取得你这个输出作为输入的目标程序的要求(网络要求,编码要求),来对你的输出进行编码(成字节流),然后再传输给它。所以这个时候,你需要对需要输出的字符串进行 encode,比如:

use Encode;
$string=”中国”;
$string_decoded=decode_utf8($string);
$string_encoded=encode(“gb2312″, $string_decoded);
print $string_encoded;

这个时候, $string_encoded 中便是以 gb2312 编码方式编码过的字节流了(它同样代表“中国”这个字符串)。
如果你直接输出 $string_decoded 而不做 encode 的话,perl 便会按这个字符串在其内存中保存的方式(也就是utf8)输出,如果你是 utf8 的环境,你可以看到正确的字符串,但如果你这个字符串里面一旦包含了大于\xFF的字节,那么perl会警告”Wide character in print…”。那为什么我 encode 了这个字符串后perl不会报这个警告呢?那是因为perl会对“字符串”做标记,decode会打上标记,encode后会去掉这个标记,一旦你输出的时候有这个标记,并且有字节大于\xFF,perl就会丢出那个警告,下次你看到这个警告,一眼就可以看出是因为你程序的某个输出没有经过编码转换成字节流的缘故的。

呃。。。我是不是有点太罗嗦了。。。
Anyway, 希望大家对 Perl 的 encoding 有个了解。

at here:

http://www.onlamp.com/pub/a/onlamp/2008/02/19/developing-restful-web-services-in-perl.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/perl -w
 
use Crypt::Blowfish;
use strict;
 
my $key = 'thisismykey';
my $text = "The content need to be crypted.";
 
my @ret;
block($text, \@ret);
 
my $cipher = new Crypt::Blowfish $key;
my $crypted = '';
 
map { $crypted .= $cipher->encrypt($_) } @ret;
 
print unpack("H*", $crypted), "\n";
 
###########################
sub block
{
    my ($string, $refArr) = @_;
 
    my $n = length($string)   /  8;
    $n++ if length($string) % 8;
 
   @$refArr= unpack("a8" x $n, $string);
    if (length($string) % 8  )
    {
        @$refArr[$#$refArr] = unpack("a8", pack("a8", @$refArr[$#$refArr]));
    }
}

[ad]

perl想到的,几乎都可以实现(当然, 其它语言也可以实现, 只是方便程序不同而已).

还有几乎无所不包的cpan

在C中, 当然可以调用C代码, 包括内嵌的C语句, 或C/C++写的动态链接库.

调用方面用的多的有两个: XS和Inline::c ,这里使用了inline::c

嵌入动态链接库:

例如我有一个运态链接库名字为libmylib.so,放在默认的目录下, 里面有个函数CheckDomain(in, out), 第一个参数为输入参数, 第二个参数是返回参数, 我们可以写一个wapper,然后像下面这样调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/perl -w
use Inline C => Config => LIBS => '-lmylib';
use Inline C;
use strict;
$| = 1;
my $ip = '10.10.10.10';
my $domain = ';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;';
my $ret = getDomain($ip, $domain);
if($ret == 0)
{
	$domain =~ s/;+//g;
	print $domain, "\n";
} else
{
	print "error\n";
	exit 1;
}
 
__END__
__C__
int getDomain(char *in, char *out)
{
	return CheckDomain(in, out);
}

 

如果不需要动态链接库, 直接嵌入C语句, 就更简单一些, 在下面直接写代码, 在上面调用即可。

注: 为何上面的$domain变量写了许多没用的分号?因为可能是C和perl的空间分配不同, C中是靠代码中自己控制的, 而perl中编码人员不需要关心。 这两个的差异会造成一个问题:perl中你分配置了2字节, 则在c中返回的参数中也只能返回2字节(会不会溢出?呀呀呀)。故在perl中多分配了一些长度。
[ad]