greenking19 / sm_crypto

Chinese national encryption algorithm SM2, SM3, SM4. Can output hex string or hex List<int>.
MIT License
15 stars 4 forks source link

长文本解密会有截断的bug #1

Closed hatjs880328s closed 2 years ago

hatjs880328s commented 2 years ago

长文本解密会有截断的bug

greenking19 commented 2 years ago

我以为没人会使用。 很高兴你使用我的🤭 具体bug能描述一下吗? 比如说文本长度

greenking19 commented 2 years ago

还有加密模式等 我好复现并修复

hatjs880328s commented 2 years ago

还有加密模式等 我好复现并修复

字节流大约200个的时候就会出现。 补码pkcs7 , 模式为cbc

hatjs880328s commented 2 years ago

还有加密模式等 我好复现并修复

解密内容是没有问题的,只是从某个位置开始,解密的结果被截断了。

jyk1987 commented 2 years ago

关注,刚准备用呢:-)

greenking19 commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

jyk1987 commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问这面这位仁兄提到的长内容被截断的问题,是确实存在吗?我现在准备也是进行对称加密加密,内容也是很长的。

hatjs880328s commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问这面这位仁兄提到的长内容被截断的问题,是确实存在吗?我现在准备也是进行对称加密加密,内容也是很长的。

存在是存在的,估计作者已经再改了吧、

hatjs880328s commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问截断的问题,有结果了吗?

jyk1987 commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问截断的问题,有结果了吗?

不知道啊,没见作者更新代码啊。

jyk1987 commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问截断的问题,有结果了吗?

解密的时候确实会有问题,希望作者可以修复下,谢谢了。 FormatException (FormatException: Invalid UTF-8 byte (at offset 3))

greenking19 commented 2 years ago

我在修复了, 稍等一下, 因为我也好久更新这个项目了 都是CBC? IV放了吗?

greenking19 commented 2 years ago

关注,刚准备用呢:-)

OK 后续我补充sm2跟sm3

请问截断的问题,有结果了吗?

CBC的IV你放了吗 CBC要放IV的

greenking19 commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零

下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');
hatjs880328s commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零

下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

能给一个联系方式吗? 一起探讨下这个问题。

jyk1987 commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零

下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

我的代码如下

  String content =
      "This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++, not subject to the many ways that things can go wrong when using bindgen or cbindgen to generate unsafe C-style bindings.This doesn't change the fact that 100% of C++ code is unsafe. When auditing a project, you would be on the hook for auditing all the unsafe Rust code and all the C++ code. The core safety claim under this new model is that auditing just the C++ side would be sufficient to catch all problems, i.e. the Rust side can be 100% safe.";

  void encode() {
    debugPrint(content.length.toString());
    String mainKey = "1234567890123456";
    String key = SM4.createHexKey(key: mainKey);
    String iv = SM4.createHexKey(key: mainKey);
    debugPrint("${key.length}:$key");
    String code = SM4.encrypt(
      data: content,
      key: key,
      mode: SM4CryptoMode.CBC,
      padding: SM4PaddingMode.PKCS7,
      iv: iv,
    );
    print(code);
    print(code.length);
    print(SM4.decrypt(
      data: code,
      key: key,
      mode: SM4CryptoMode.CBC,
      padding: SM4PaddingMode.PKCS7,
      iv: iv,
    ));
  }

报错如下

════════ Exception caught by gesture ═══════════════════════════════════════════
The following FormatException was thrown while handling a gesture:
Invalid UTF-8 byte (at offset 342)
hatjs880328s commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零

下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零 下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

我的代码如下

  String content =
      "This library provides a safe mechanism for calling C++ code from Rust and Rust code from C++, not subject to the many ways that things can go wrong when using bindgen or cbindgen to generate unsafe C-style bindings.This doesn't change the fact that 100% of C++ code is unsafe. When auditing a project, you would be on the hook for auditing all the unsafe Rust code and all the C++ code. The core safety claim under this new model is that auditing just the C++ side would be sufficient to catch all problems, i.e. the Rust side can be 100% safe.";

  void encode() {
    debugPrint(content.length.toString());
    String mainKey = "1234567890123456";
    String key = SM4.createHexKey(key: mainKey);
    String iv = SM4.createHexKey(key: mainKey);
    debugPrint("${key.length}:$key");
    String code = SM4.encrypt(
      data: content,
      key: key,
      mode: SM4CryptoMode.CBC,
      padding: SM4PaddingMode.PKCS7,
      iv: iv,
    );
    print(code);
    print(code.length);
    print(SM4.decrypt(
      data: code,
      key: key,
      mode: SM4CryptoMode.CBC,
      padding: SM4PaddingMode.PKCS7,
      iv: iv,
    ));
  }

报错如下

════════ Exception caught by gesture ═══════════════════════════════════════════
The following FormatException was thrown while handling a gesture:
Invalid UTF-8 byte (at offset 342)

你这个问题最终输出 原因: 看源码 将utf8 转换 -》 修改为 输出List即可,业务按需自己转。 // adjust output if (outputType != SM4OutputMode.Array) { if (cryptFlag != DECRYPT) { // encrypt, out hex string return _arrayToHex(outArray); } else { return outArray; } } else { return outArray; }

hatjs880328s commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零

下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

1.IV加了 2.补0这问题 服务端应该加密方式统一,短的可以,长的不行很奇怪。我直接拿一个有问题的例子了。 note: 我们的数据是 proto buffer 序列化之后的,所以最终输出不可以使用utf8 编码输出。我在上面的回复也写了。让业务开发自己决定输出什么。

有问题的数据:

输入: _Uint8ArrayView ([134, 44, 21, 167, 215, 14, 215, 75, 214, 17, 151, 183, 226, 98, 230, 6, 223, 153, 106, 238, 144, 94, 205, 100, 120, 242, 123, 124, 79, 148, 196, 218, 69, 44, 185, 252, 251, 180, 30, 140, 88, 217, 75, 54, 231, 45, 59, 0, 0, 110, 165, 227, 16, 120, 136, 213, 38, 57, 224, 109, 155, 253, 180, 55, 194, 72, 238, 154, 125, 151, 244, 252, 138, 99, 16, 118, 204, 57, 1, 11, 241, 21, 162, 163, 58, 18, 227, 96, 211, 254, 42, 90, 186, 79, 55, 130, 121, 86, 129, 106, 107, 72, 78, 169, 110, 237, 235, 174, 199, 79, 178, 222, 124, 115, 235, 44, 249, 116, 113, 210, 182, 249, 106, 8, 239, 28, 122, 67, 155, 102, 215, 208, 118, 64, 105, 110, 196, 179, 135, 46, 224, 97, 94, 85, 161, 31, 70, 152, 109, 237, 24, 109, 254, 209, 20, 23, 252, 195, 233, 3, 34, 140, 197, 236, 85, 198, 174, 76, 189, 184, 193, 3, 246, 133, 126, 179])

输出: [10, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136, 18, 22, 10, 7, 99, 111, 110, 116, 101, 110, 116, 18, 11, 26, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136, 18, 128, 1, 10, 4, 100, 97, 116, 97, 18, 120, 42, 118, 10, 28, 10, 8, 99, 104, 97, 116, 84, 121, 112, 101, 18, 16, 26, 14, 99, 104, 97, 116, 86, 105, 100, 101, 111, 83, 116, 97, 116, 101, 10, 13, 10, 7, 105, 115, 86, 105, 100, 101, 111, 18, 2, 32, 2, 116, 111, 18, 2, 50, 84, 121, 112, 101, 18, 24, 26, 22, 99, 104, 97, 116, 86, 105, 100, 101, 111, 67, 97, 110, 99, 101, 108, 67, 97, 108, 108, 105, 110, 103, 10, 22, 10, 7, 99, 111, 110, 116, 101, 110, 116, 18, 11, 26, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136]

jyk1987 commented 2 years ago

我的也是,短的可以,长的就不行了。

greenking19 commented 2 years ago

好吧 我找到问题所在了...

greenking19 commented 2 years ago

我刚才测试 长度20000的文本都没有问题. 你们方便给个示例吗? 我好复现. 还有一点就是你们是本地加密解密还是解密后端回来的数据? 如果是解密后端回来的数据, 还需要问一下后端是否补零, 我这个是默认自动补零 下面我这个示例运行没发现问题 20000长度的文本

final _random = Random();
int textLength = 20000;
const _availableChars =
    'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final randomString = List.generate(textLength,
        (index) => _availableChars[_random.nextInt(_availableChars.length)])
    .join();

String key = SM4.createHexKey(key: '12345678909876');

String iv = SM4.createHexKey(key: '12345678909876');
String cbcEncryptData = SM4.encrypt(
  data: randomString,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔒 CBC EncryptptData:\n $cbcEncryptData');
String cbcDecryptData = SM4.decrypt(
  data: cbcEncryptData,
  key: key,
  mode: SM4CryptoMode.CBC,
  padding: SM4PaddingMode.PKCS7,
  iv: iv,
);
print('🔑 CBC DecryptData:\n $cbcDecryptData');

1.IV加了 2.补0这问题 服务端应该加密方式统一,短的可以,长的不行很奇怪。我直接拿一个有问题的例子了。 note: 我们的数据是 proto buffer 序列化之后的,所以最终输出不可以使用utf8 编码输出。我在上面的回复也写了。让业务开发自己决定输出什么。

有问题的数据:

输入: _Uint8ArrayView ([134, 44, 21, 167, 215, 14, 215, 75, 214, 17, 151, 183, 226, 98, 230, 6, 223, 153, 106, 238, 144, 94, 205, 100, 120, 242, 123, 124, 79, 148, 196, 218, 69, 44, 185, 252, 251, 180, 30, 140, 88, 217, 75, 54, 231, 45, 59, 0, 0, 110, 165, 227, 16, 120, 136, 213, 38, 57, 224, 109, 155, 253, 180, 55, 194, 72, 238, 154, 125, 151, 244, 252, 138, 99, 16, 118, 204, 57, 1, 11, 241, 21, 162, 163, 58, 18, 227, 96, 211, 254, 42, 90, 186, 79, 55, 130, 121, 86, 129, 106, 107, 72, 78, 169, 110, 237, 235, 174, 199, 79, 178, 222, 124, 115, 235, 44, 249, 116, 113, 210, 182, 249, 106, 8, 239, 28, 122, 67, 155, 102, 215, 208, 118, 64, 105, 110, 196, 179, 135, 46, 224, 97, 94, 85, 161, 31, 70, 152, 109, 237, 24, 109, 254, 209, 20, 23, 252, 195, 233, 3, 34, 140, 197, 236, 85, 198, 174, 76, 189, 184, 193, 3, 246, 133, 126, 179])

输出: [10, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136, 18, 22, 10, 7, 99, 111, 110, 116, 101, 110, 116, 18, 11, 26, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136, 18, 128, 1, 10, 4, 100, 97, 116, 97, 18, 120, 42, 118, 10, 28, 10, 8, 99, 104, 97, 116, 84, 121, 112, 101, 18, 16, 26, 14, 99, 104, 97, 116, 86, 105, 100, 101, 111, 83, 116, 97, 116, 101, 10, 13, 10, 7, 105, 115, 86, 105, 100, 101, 111, 18, 2, 32, 2, 116, 111, 18, 2, 50, 84, 121, 112, 101, 18, 24, 26, 22, 99, 104, 97, 116, 86, 105, 100, 101, 111, 67, 97, 110, 99, 101, 108, 67, 97, 108, 108, 105, 110, 103, 10, 22, 10, 7, 99, 111, 110, 116, 101, 110, 116, 18, 11, 26, 9, 229, 183, 178, 229, 143, 150, 230, 182, 136]

我找到问题了

greenking19 commented 2 years ago

我就说我本地怎么复现不了. 原来是我本地代码早就修复了这个问题. 但是我一直没有更新版本. 一切都是懒导致的🤣 我现在就推送版本,你们更新即可

greenking19 commented 2 years ago

已经更新 1.0.2 切换版本即可 sm2 sm3 周末补上

hatjs880328s commented 2 years ago

已经更新 1.0.2 切换版本即可 sm2 sm3 周末补上

目前来看还是不对奥。解密直接返回 List(int) 还是不对。

greenking19 commented 2 years ago

已经更新 1.0.2 切换版本即可 sm2 sm3 周末补上

目前来看还是不对奥。解密直接返回 List(int) 还是不对。

微信说吧 ID: NoBeginNoMore

hatjs880328s commented 2 years ago

已经更新 1.0.2 切换版本即可 sm2 sm3 周末补上

而且上面说了,解密的时候,你直接用 utf8 编码字符串有时候会报错, 直接返回 int 字节数组即可。

jyk1987 commented 2 years ago

已经更新 1.0.2 切换版本即可 sm2 sm3 周末补上

目前来看还是不对奥。解密直接返回 List(int) 还是不对。

已经测试可以了,感谢🙏 期待sm2和sm3