cnvcl icon indicating copy to clipboard operation
cnvcl copied to clipboard

请教:SM4使用java中的byte数组加密结果不一致

Open Yang-Ya-Chao opened this issue 2 years ago • 3 comments

java的key: byte[] keyBytes={17,34,79,88,-120,16,64,56,40,37,121,81,-53,-35,85,102} 加密模式:ECB 填充模式:PKCS7 请教怎么使用cnvcl的SM4模块加密呢 使用如下代码加密的结果与java不一致: --CNVCL加密代码 const TmpKeytmp: array[0..15] of Byte = (17, 34, 79, 88, 255 - 120, 16, 64, 56, 40, 37, 121, 81, 255 - 53, 255 - 35, 85, 102); procedure TFormCrypt.btnSm4Click(Sender: TObject) function ArraytoTbytes(bs: array of byte): Tbytes; begin setlength(Result, Length(bs)); Move(bs[0], Result[0], Length(bs)); end; var Output: AnsiString; Len: Integer; TmpSm4Iv: array[0..15] of Byte; IvStr: AnsiString; s: ansistring; m, n: string; KeyBytes, ResBytes, DataBytes: TBytes; begin Len := Length(AnsiString(MMSm4.Text)); if Len < 16 then Len := 16 else Len := (((Len - 1) div 16) + 1) * 16; SetLength(Output, Len); ZeroMemory(@(Output[1]), Len); KeyBytes := ArraytoTbytes(TmpKeytmp);//TEncoding.Default.GetBytes(MMKey.Text); DataBytes := TEncoding.Default.GetBytes(MMSm4.Text); BytesAddPKCS7Padding(DataBytes, SM4_BLOCKSIZE); ResBytes := SM4EncryptEcbBytes(KeyBytes, DataBytes); MMCode.Text := BytesToHex(ResBytes); end;

Yang-Ya-Chao avatar Jun 04 '22 07:06 Yang-Ya-Chao

把Java的写法以及待加密的明文和各自加的密文都贴出来吧,问题很可能在编码上。

shanzhashu avatar Jun 04 '22 07:06 shanzhashu

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

Yang-Ya-Chao avatar Jun 04 '22 07:06 Yang-Ya-Chao

这休假休的可够长的……

shanzhashu avatar Sep 29 '22 09:09 shanzhashu

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

Yang-Ya-Chao avatar Oct 11 '22 08:10 Yang-Ya-Chao

抱歉哈,没有关注iss消息,这个是接到的对方文档说明 加密说明 1、整个接口的 XML 以密文传输,适用国密 sm4 国家已开放算法,提供的是 java 加 密,解 密 jar,如果是 java 后台在引入 jar 后可直接调用。 2、加密调用 common-endecrypt-2.0.0.jar 中的 Sm4HexEn.encode("明文")方法; 3、解密调用 common-decrypt-2.0.0.jar 中的 Sm4HexDe.decode("密文");方法 4、如果非 java 程序进行加解密需自行实现,有两种方式【自行实现】或【将 JAR 转 DLL】 算法使用 sm4 的 ECB 模式 算法密钥 byte[] keyBytes = { 17, 34, 79, 88, -120, 16, 64, 56, 40, 37, 121, 81, -53, -35, 85, 102 }; 自行实现算法时不要调用 Base64 编码,需直接将加密结果转成 16 进制 5,如果是调用动态库,可将 jar 包转成 DLL 来调用,这样最简单

Yang-Ya-Chao avatar Dec 21 '22 05:12 Yang-Ya-Chao

新建文本文档.txt 密文跟明文我放这里了,这个是java给的示例

Yang-Ya-Chao avatar Dec 21 '22 05:12 Yang-Ya-Chao

不同端的分组加密考虑的因素有很多: 1、每块的加密算法(DES/AES/SM4等) 2、数据分块的每块大小(128/192/256等) 3、块与块之间的运算模式(ECB/CBC等) 4、数据不满足整数块时如何填充(PKCS1/PKCS7等) 5、密文是否要转变成可读的(Hex/Base64等) 6、明文如果是字符串,加密时还有字符编码问题(UTF8/UTF16/Ansi等) 但凡有一处和所需的不一样,加密出来的结果就对不上号,还是得挨个去研究。

你贴的内容里,1/2/3/4/5都确定了(虽然4对方文档里没说是PKCS7,但你一楼写了用PKCS7,就算它是) 但6你用的TEncoding.Default.GetBytes,我估计Java里常用的是UTF8,可以改成UTF8编码试一试。

总体顺序的确是先文本转UTF8的Bytes,再BytesAddPKCS7Padding,再SM4EncryptEcbBytes,再BytesToHex, 解密则是倒过来,先HexToBytes,再SMDecryptEcbBytes,再BytesRemovePKCS7Padding,再UTF8解码。

shanzhashu avatar Dec 21 '22 06:12 shanzhashu

好勒谢谢大哥,我试试

Yang-Ya-Chao avatar Dec 21 '22 08:12 Yang-Ya-Chao

改成utf8的话,密文长度是一模一样的了,但是结果还是对不上,思路顺序应该是没问题的,其他的三方的我也对过都没问题,他这个密文我对不上,有可能是他们自己写的不是标准的sm4吧,其他原因我找不出来了

Yang-Ya-Chao avatar Dec 21 '22 08:12 Yang-Ya-Chao

刚看你代码还有一个要注意的点,Java的byte数组是有符号的所以对方提供的密钥有负值,比如-120,而我们加解密的Key的array[] of Byte是无符号的,你用255-120代替-120,这一点你那边能否确认正确?

shanzhashu avatar Dec 21 '22 10:12 shanzhashu

不能确认是不是这个原因引起的,d没有负数的数组,咨询过好多人说是255-120 与-120是一致的,但是我自己并不确认,而且也没法确认是不是跟java的区别是这里造成的,算了不纠结了,谢谢大哥,sm4的思路搞明白就行了,主要是这个加密我之前没有对接出来有点梗着,所以来问问,应该是其他原因影响,而不是sm4这个加密代码本身的问题

Yang-Ya-Chao avatar Dec 22 '22 00:12 Yang-Ya-Chao

var B: Byte; begin B := Byte(-120); Caption := IntToStr(B);

得到的结果是136,也就是说应该是256-120,而不是255。

shanzhashu avatar Dec 23 '22 03:12 shanzhashu

这是来自QQ邮箱的假期自动回复邮件。   您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。

Yang-Ya-Chao avatar Feb 12 '23 04:02 Yang-Ya-Chao