发表日期:2019-08 文章编辑:小灯 浏览次数:1748
最近公司新启动一个项目,老大定了一套前后台加密交互方案:
前台发送请求:RSA公钥加密 - 压缩 - Base64编码;
后台返回响应:RSA私钥加密 - 压缩 - RSA私钥加签 - Base64编码;
前台处理响应:RSA公钥验签 - Base64解码 - 解压 - RSA公钥解密。
因为iOS这边验签时需要der格式的公钥,所以RSA秘钥由iOS端生成。
cd dqsrsa_key
openssl
genrsa out rsa_private_keypem

rsarsa_private_keypem out rsa_public_keypem pubout
reqkey rsa_private_keypem out rsa_certReqcsr

step2. 由请求文件生成证书rsa_cert.crt,并设置有效时间为10年
x509 req days rsa_certReqcsr signkey rsa_private_keypem out rsa_certcrt

step3. 由证书文件生成der格式的公钥
x509 outform derrsa_certcrt out rsa_public_keyder
pkcs12 export out iOS_rsa_private_keyp12 inkey rsa_private_keypemrsa_certcrt

pkcs8 topk8rsa_private_keypem out pem nocrypt

导入#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;
}