将Java MD5哈希生成代码转换为等效Perl代码求助
问题分析
你的Java代码和Perl代码结果不匹配的核心原因是Java的hex方法对MD5字节数组的处理顺序是逆序的,而Perl的Digest::MD5->hexdigest()生成的是标准顺序的十六进制字符串。
看Java里的hex方法:
public static String hex(byte[] bytes) { char[] c = new char[bytes.length * 2]; for (int i = 0; i < bytes.length; i++) { // 这里的j是从数组末尾开始往前计算位置 int j = (bytes.length - i - 1) * 2; c[(j + 0)] = HEX[(bytes[i] >> 4 & 0xF)]; c[(j + 1)] = HEX[(bytes[i] >> 0 & 0xF)]; } return new String(c); }
比如MD5字节数组是[b0, b1, b2, ..., b15],正常的十六进制应该是b0的十六进制 + b1的十六进制 + ... + b15的十六进制,但你的Java代码会生成b15的十六进制 + b14的十六进制 + ... + b0的十六进制——也就是把整个字节数组的十六进制表示完全反转了。
而你的Perl代码用的是标准的hexdigest(),生成的是正常顺序的结果,自然和Java的不一样。
修正后的Perl代码
要让Perl代码和Java代码结果一致,我们需要模拟Java的逆序处理逻辑。这里有两种实现方式:
方式一:操作字节数组反转后转十六进制
use Digest::MD5 qw(md5); my $ffname = "C:/Users/yuvarar/Desktop/BMS/dcmfiles/Test.dcm"; open my $fh, '<', $ffname or die "Can't open file: $!"; # 获取MD5的原始字节数组,然后反转 my $md5_bytes = md5($fh); my $reversed_bytes = reverse $md5_bytes; # 把反转后的字节数组转成十六进制字符串 my $hash = unpack('H*', $reversed_bytes); close $fh; printf("md5_hex:%s\n", $hash);
方式二:先拿到标准十六进制字符串,再按两位一组反转
use Digest::MD5 qw(hexdigest); my $ffname = "C:/Users/yuvarar/Desktop/BMS/dcmfiles/Test.dcm"; open my $fh, '<', $ffname or die "Can't open file: $!"; my $ctx = Digest::MD5->new; $ctx->addfile($fh); my $standard_hex = $ctx->hexdigest; # 把标准十六进制字符串按两位拆分,反转数组后再拼接 my @hex_pairs = $standard_hex =~ /(..)/g; my $hash = join('', reverse @hex_pairs); close $fh; printf("md5_hex:%s\n", $hash);
这两种方式都能得到和你Java代码完全一致的MD5哈希值,你可以根据自己的习惯选择。另外,建议你的Perl代码使用词法文件句柄(my $fh)代替旧式的FILE,并且加上错误处理(or die),这样代码更健壮。
内容的提问来源于stack exchange,提问作者Rajesh Kumar Yuvaraj
相关产品推荐
相关产品推荐

