如何使用openssl命令行工具解密Perl Crypt::DES加密的密文
如何用OpenSSL命令行解密Perl Crypt::DES加密的密文?
问题背景
我需要使用命令行工具openssl解密由Perl模块Crypt::CBC(基于DES)加密的密文。
加密用的Perl脚本
#!/usr/bin/perl -w use strict; use 5.010; use Getopt::Long qw(:config no_ignore_case); use Crypt::CBC; ### initialization &GetOptions("mode=s" => \(my $mode = '')); my $secret = q/;[qO7e<_sZmR8Krhf>}]mRY`y)BI8"WEF*2nmL^o'WMKA=uEt1/; my $key = pack('H*', $secret); open(my $fh, '>', 'key.bin'); $fh->print($key); $fh->close(); my $cipher = Crypt::CBC->new( -key => $key, -cipher => 'DES' ); ### read file my $filename = shift @ARGV; open($fh, '<', $filename) or die "$!"; my $cchRead = read($fh, my $buffer, -s $fh); close($fh); die "$!" unless defined($cchRead); ### encrypt if ($mode eq 'encrypt') { print $cipher->encrypt($buffer); } ### decrypt else { print $cipher->decrypt($buffer); }
脚本使用方式
$ ./cipher.pl --mode=encrypt foo.txt > foo.encrypted # 加密明文 $ ./cipher.pl --mode=decrypt foo.encrypted # 解密密文
我尝试了以下OpenSSL命令,但均未成功:
$ openssl enc -des -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-cbc -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-cfb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-cfb1 -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-cfb8 -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ecb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede-cbc -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede-cfb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede-ofb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede3 -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede3-cbc -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede3-cfb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ede3-ofb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des-ofb -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -des3 -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -desx -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted' $ openssl enc -desx-cbc -salt -pbkdf2 -pass file:key.bin -d -in 'foo.encrypted'
解决方案
失败原因分析
你之前的命令存在三个核心错误:
- 多余的密钥推导参数:脚本直接使用
pack('H*', $secret)生成的原始密钥,没有通过盐和PBKDF2推导密钥,-salt和-pbkdf2选项完全没必要,反而会导致OpenSSL错误处理密钥。 - 未指定正确的IV:Crypt::CBC默认会生成随机8字节IV(DES块大小),并将其前缀在密文头部,OpenSSL不会自动识别这个IV,必须手动提取并指定。
- 模式选择错误:Crypt::CBC默认使用CBC模式,只有
-des-cbc是正确的加密模式选项,其他模式无法匹配加密逻辑。
解密步骤
方式一:分步操作(生成中间文件)
- 从密文中提取前8字节的IV:
dd if=foo.encrypted bs=1 count=8 of=iv.bin
- 提取去除IV后的纯密文:
dd if=foo.encrypted bs=1 skip=8 of=ciphertext.bin
- 执行OpenSSL解密命令:
openssl enc -des-cbc -d -in ciphertext.bin -iv "$(cat iv.bin | xxd -p)" -K "$(cat key.bin | xxd -p)"
方式二:单命令直接解密(无中间文件)
合并提取IV和密文的操作,一步完成解密:
openssl enc -des-cbc -d -in <(dd if=foo.encrypted bs=1 skip=8 2>/dev/null) -iv "$(dd if=foo.encrypted bs=1 count=8 2>/dev/null | xxd -p)" -K "$(cat key.bin | xxd -p)"
参数说明
xxd -p:将二进制的密钥和IV转换为十六进制字符串,符合OpenSSL-K(密钥)和-iv(初始化向量)参数的格式要求。- Crypt::CBC默认使用PKCS#5填充,和OpenSSL
enc命令的默认填充规则兼容,无需额外指定填充方式。
内容的提问来源于stack exchange,提问作者Cody
相关产品推荐
相关产品推荐

