muzipiao / GMObjC

SM2/SM3/SM4/ECDH crypto library based on OpenSSL.
https://muzipiao.github.io/2019/08/iOS-%E4%BD%BF%E7%94%A8-SM2-SM4-%E5%8A%A0%E8%A7%A3%E5%AF%86-SM2-%E7%AD%BE%E5%90%8D%E9%AA%8C%E7%AD%BE%E5%8F%8A-SM3-%E6%91%98%E8%A6%81/
MIT License
346 stars 88 forks source link

真难啊! #58

Closed Blasphel closed 2 years ago

Blasphel commented 2 years ago

感谢大佬! 谢谢

WGFcode commented 2 years ago

感谢大佬! 谢谢

java用的什么工具类

muzipiao commented 2 years ago

BouncyCastle

WGFcode commented 2 years ago

BouncyCastle

ios端无法解密java生成的密文,有什么解决方法吗

muzipiao commented 2 years ago

提问题你得说清楚情况(日志、截图、错误信息等),靠这一句话让我猜吗?

Blasphel commented 2 years ago

WGF的问题应该是没有看README。里面有答案,我改了一下你们的C1C3C2改成C1C2C3 看了里面的改出来感觉还是有些问题 。

这个排序只在ASN1里使用了么? 加密解密过程里的哪里改呢大佬

Blasphel commented 2 years ago

就比如 SM2种 C1C2C3 1.PC端加密后的 BAtId4JBugT7Sj/fLTtXLS9ItojLzFO/lBbGs7AhKiwU9yZ7F+bhTA22ucEhQ7pm16komkkhXkFB/jJHlWuVyKoYdc8QhV1D5K9eC9GiBjB279S8kgN1/IrsmQeIIF3Ss5zo+hB3f+f64JB5RNAel6+rQgMuaMdh+A== 为最初密文加密后的我需要解密 但是看得出这个是base64后的 2.我通过MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgRTq0zQBhp59GJu1U38IES0JnwVuznIX9dF 9wgNet9kSgCgYIKoEcz1UBgi2hRANCAARGfwCMCFsO6KTDucGgEHqFSJFtQ4nCR560xyhdI+REYjwj7kiSuUNw smBbXKin0V4Di13CdVFbmkIVrDf8bdCk写入文件再读出来 获取到我们iOS可以使用的秘钥453AB4CD0061A79F4626ED54DFC2044B4267C15BB39C85FD745F7080D7ADF644 使用 3.我将1中的字段base64解码后ASN1 编码再解密 。 但是解密结果为nil 哪里出错了呢

3的代码
miyao2 = [self hexStringFromData:[[NSData alloc]initWithBase64EncodedString:miyao2 options:NSDataBase64DecodingIgnoreUnknownCharacters]]; miyao2 = [GMSm2Utils asn1EncodeWithC1C3C2:miyao2] ;

NSString *deResult5 = [GMSm2Utils decryptToHex:miyao2 privateKey:priKey]; // 解密为 Hex 格式明文
NSString *deResult6 = [GMSm2Utils decryptToText:miyao2 privateKey:priKey]; // 
WGFcode commented 2 years ago

提问题你得说清楚情况(日志、截图、错误信息等),靠这一句话让我猜吗?

image

和PC端确认了密文就是C1C3C2,iOS中用PC端提供的公私钥可以正常加解密,但是拿到PC端的密文无法解密,大佬帮忙看下

muzipiao commented 2 years ago

openssl 默认排序为 C1C3C2,且进行了 ASN1 编码格式,所以解密前,确保密文为 ANS1 编码的 C1C3C2 密文。 java 端密文一般为 C1C2C3 顺序排列,转为 C1C3C2 顺序,然后 ASN1 编码,将编码后的密文使用 API 解密即可。 注意:密文一般不包含 04 开头(04开头一般代表非压缩),看你们这里都是 04 开头,转换时把 04 去掉,你们试一下。 下方转换参考 Readme 中 【ASN1 编码解码】章节:

/// 将 c1c2c3 格式密文转为 c1c3c2
/// @param cipertext c1c2c3 格式16进制编码密文
- (nullable NSString *)c1c2c3Toc1c3c2:(NSString *)cipertext {
    if ([cipertext hasPrefix:@"04"]) {
        cipertext = [cipertext substringFromIndex:2];
    }
    if (cipertext.length < 192) {
        return nil;
    }
    NSString *c1 = [cipertext substringToIndex:128];
    NSString *c3 = [cipertext substringFromIndex:(cipertext.length - 64)];
    NSString *c2 = [cipertext substringWithRange:NSMakeRange(128, cipertext.length - c1.length - c3.length)];
    NSString *c1c3c2 = [NSString stringWithFormat:@"%@%@%@", c1, c3, c2];
    return c1c3c2;
}
Blasphel commented 2 years ago

openssl 默认排序为 C1C3C2,且进行了 ASN1 编码格式,所以解密前,确保密文为 ANS1 编码的 C1C3C2 密文。 java 端密文一般为 C1C2C3 顺序排列,转为 C1C3C2 顺序,然后 ASN1 编码,将编码后的密文使用 API 解密即可。 注意:密文一般不包含 04 开头(04开头一般代表非压缩),看你们这里都是 04 开头,转换时把 04 去掉,你们试一下。 下方转换参考 Readme 中 【ASN1 编码解码】章节:

/// 将 c1c2c3 格式密文转为 c1c3c2
/// @param cipertext c1c2c3 格式16进制编码密文
- (nullable NSString *)c1c2c3Toc1c3c2:(NSString *)cipertext {
    if ([cipertext hasPrefix:@"04"]) {
        cipertext = [cipertext substringFromIndex:2];
    }
    if (cipertext.length < 192) {
        return nil;
    }
    NSString *c1 = [cipertext substringToIndex:128];
    NSString *c3 = [cipertext substringFromIndex:(cipertext.length - 64)];
    NSString *c2 = [cipertext substringWithRange:NSMakeRange(128, cipertext.length - c1.length - c3.length)];
    NSString *c1c3c2 = [NSString stringWithFormat:@"%@%@%@", c1, c3, c2];
    return c1c3c2;
}

这个转换我是有转换过的 PC的我给过去他们C1C2C3都能加密 但是我这边就 (⊙o⊙)… EMMMMM

Blasphel commented 2 years ago

我去掉04试试

Blasphel commented 2 years ago

可以了 果然是多了个04 谢谢大佬!

WGFcode commented 2 years ago

感谢大佬