iOS开发日常-前后台数据交互之RSA公钥验签

背景概述

  最近公司新启动一个项目,老大定了一套前后台加密交互方案:

前台发送请求:RSA公钥加密 - 压缩 - Base64编码;

后台返回响应:RSA私钥加密 - 压缩 - RSA私钥加签 - Base64编码;

前台处理响应:RSA公钥验签 - Base64解码 - 解压 - RSA公钥解密。

  因为iOS这边验签时需要der格式的公钥,所以RSA秘钥由iOS端生成。

OpenSSL生成秘钥

  • 创建一个临时文件夹,cd到该文件夹下,执行openssl
cd /Users/dqs/Desktop/rsa_key
openssl

  • 生成模长为1024bit的私钥文件rsa_private_key.pem(该文件作为后续文件的基石,具体iOS端和Java端的私钥文件需另行生成)
genrsa -out rsa_private_key.pem 1024

  • 由私钥文件生成公钥文件(该公钥文件即为最终的公钥文件)
rsa -in rsa_private_key.pem -out rsa_public_key.pem -pubout

  • 生成iOS本地RSA公钥验签时需要的der格式公钥
    step1. 由私钥文件生成请求文件rsa_certReq.csr文件(信息、密码等正常填写,可选)
req -new -key rsa_private_key.pem -out rsa_certReq.csr


step2. 由请求文件生成证书rsa_cert.crt,并设置有效时间为10年

扫描二维码关注公众号,回复: 5324768 查看本文章
x509 -req -days 3650 -in rsa_certReq.csr -signkey rsa_private_key.pem -out rsa_cert.crt


step3. 由证书文件生成der格式的公钥

x509 -outform der -in rsa_cert.crt -out rsa_public_key.der

  • 生成供iOS使用的私钥文件iOS_rsa_private_key.p12(此处需要设置密码,后续解密时会用到)
pkcs12 -export -out iOS_rsa_private_key.p12 -inkey rsa_private_key.pem -in rsa_cert.crt

  • 生成供Java使用的私钥Java_pkcs8_private_key.pem
pkcs8 -topk8 -in rsa_private_key.pem -out Java_pkcs8_private_key.pem -nocrypt

  • 全部执行成功后,会生成如下文件:

iOS本地RSA公钥验签

导入#import <CommonCrypto/CommonCrypto.h>
/**
 * 根据der格式的公钥获取验签时需要的SecKeyRef
 */
+ (SecKeyRef)fetchPublicSecKeyRef:(NSString *)pubDerPath; {
    static SecKeyRef keyRef = nil;
    NSData *certificateData = [NSData dataWithContentsOfFile:pubDerPath];
    SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData);
    SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    SecTrustRef myTrust;
    OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
    SecTrustResultType trustResult;
    if (status == noErr) {
        status = SecTrustEvaluate(myTrust, &trustResult);
    }
    keyRef = SecTrustCopyPublicKey(myTrust);
    CFRelease(myCertificate);
    CFRelease(myPolicy);
    CFRelease(myTrust);
    return keyRef;
}

/**
 * 根据加密数据和签名验证
 *  @param plainData 加密数据
 *  @param signature 签名
 **/
+ (BOOL)rsaSHA256VerifyData:(NSData *)plainData withSignature:(NSData *)signature {
    SecKeyRef key = [self fetchPublicSecKeyRef:[[NSBundle mainBundle] pathForResource:@"rsa_public_key" ofType:@"der"]];
    size_t signedHashBytesSize = SecKeyGetBlockSize(key);
    const void* signedHashBytes = [signature bytes];
    size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;
    uint8_t* hashBytes = malloc(hashBytesSize);
    if (!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {
        return NO;
    }
    OSStatus status = SecKeyRawVerify(key,
                                      kSecPaddingPKCS1SHA256,
                                      hashBytes,
                                      hashBytesSize,
                                      signedHashBytes,
                                      signedHashBytesSize);
    return status == errSecSuccess;
}

猜你喜欢

转载自blog.csdn.net/FTD_SL/article/details/86626969
今日推荐