iOS RSA加密與SHA簽名|與Java完全同步

一篇搞定RSA加密與SHA簽名|與Java完全同步??

轉(zhuǎn)載:https://www.cnblogs.com/On1Key/p/5459144.html

基礎(chǔ)知識(shí)

什么是RSA?

答:RSA是一種非對(duì)稱加密算法,常用來對(duì)傳輸數(shù)據(jù)進(jìn)行加密,配合上數(shù)字摘要算法,也可以進(jìn)行文字簽名。

RSA加密中padding?

答:padding即填充方式,由于RSA加密算法中要加密的明文是要比模數(shù)小的,padding就是通過一些填充方式來限制明文的長(zhǎng)度。后面會(huì)詳細(xì)介紹padding的幾種模式以及分段加密。

加密和加簽有什么區(qū)別?

答:加密:公鑰放在客戶端,并使用公鑰對(duì)數(shù)據(jù)進(jìn)行加密,服務(wù)端拿到數(shù)據(jù)后用私鑰進(jìn)行解密;

加簽:私鑰放在客戶端,并使用私鑰對(duì)數(shù)據(jù)進(jìn)行加簽,服務(wù)端拿到數(shù)據(jù)后用公鑰進(jìn)行驗(yàn)簽。

前者完全為了加密;后者主要是為了防惡意攻擊,防止別人模擬我們的客戶端對(duì)我們的服務(wù)器進(jìn)行攻擊,導(dǎo)致服務(wù)器癱瘓。

基本原理


RSA使用“密鑰對(duì)”對(duì)數(shù)據(jù)進(jìn)行加密解密,在加密解密前需要先生存公鑰(Public Key)和私鑰(Private Key)。

公鑰(Public key):?用于加密數(shù)據(jù). 用于公開, 一般存放在數(shù)據(jù)提供方, 例如iOS客戶端。

私鑰(Private key):?用于解密數(shù)據(jù). 必須保密, 私鑰泄露會(huì)造成安全問題。

iOS中的Security.framework提供了對(duì)RSA算法的支持,這種方式需要對(duì)密匙對(duì)進(jìn)行處理, 根據(jù)public key生成證書, 通過private key生成p12格式的密匙。想想jave直接用字符串進(jìn)行加密解密簡(jiǎn)單多了。(⊙o⊙)…

實(shí)戰(zhàn)

證書生成

RSA加密這塊公鑰、私鑰必不可少的。Apple是不支持直接使用字符串進(jìn)行加密解密的,推薦使用p12文件。這邊教大家去生成在加密中使用到的所有文件,并提供給Java使用,想當(dāng)年這個(gè)公鑰私鑰搞了半天了。 %>_<%?

這里將會(huì)生成iOS和java使用的一套公私鑰,記住 只是生成了一套 兩端使用的不同文件,需要多套的話可以再操作一波生成第二套。

生成模長(zhǎng)為1024bit的私鑰

openssl genrsa -out private_key.pem 1024

生成certification require file

openssl req -new -key private_key.pem -out rsaCertReq.csr

生成certification 并指定過期時(shí)間

openssl x509 -req -days3650-in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt

生成公鑰供iOS使用

openssl x509 -outform der -in rsaCert.crt -out public_key.der

生成私鑰供iOS使用 這邊會(huì)讓你輸入密碼,后期用到在生成secKeyRef的時(shí)候會(huì)用到這個(gè)密碼

openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt

生成pem結(jié)尾的公鑰供Java使用

openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout

生成pem結(jié)尾的私鑰供Java使用

openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt

以上所有的步驟都是在終端下完成的哦 (^__^)

生成公鑰和私鑰的secKeyRef

//根據(jù)你的p12文件生成私鑰對(duì)應(yīng)的SecKeyRef 這邊返回若是nil 請(qǐng)檢查你p12文件的生成步驟-?

-(SecKeyRef)getPrivateKeyRefrenceFromData:(NSData*)p12Data password:(NSString*)password {

SecKeyRef privateKeyRef = NULL;

NSMutableDictionary * options = [[NSMutableDictionary alloc] init];

[options setObject: password forKey:(__bridge id)kSecImportExportPassphrase];

CFArrayRef items = CFArrayCreate(NULL,0,0, NULL);

OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data, (__bridge CFDictionaryRef)options, &items);if(securityError == noErr && CFArrayGetCount(items) >0) {

? ? CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items,0);

? ? SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);

? ? securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);

? ? if(securityError != noErr) {

? ? ? ? privateKeyRef = NULL;

? ? }

}

CFRelease(items);return privateKeyRef;

}


-//根據(jù)你的der文件公鑰對(duì)應(yīng)的SecKeyRef

- (SecKeyRef)getPublicKeyRefrenceFromeData:? ? (NSData*)derData {

SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)derData);

SecPolicyRef myPolicy = SecPolicyCreateBasicX509();

SecTrustRef myTrust;

OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);

SecTrustResultType trustResult;if(status == noErr) {

? ? status = SecTrustEvaluate(myTrust, &trustResult);

}

SecKeyRef securityKey = SecTrustCopyPublicKey(myTrust);

CFRelease(myCertificate);

CFRelease(myPolicy);

CFRelease(myTrust);return securityKey;

}


加密與解密


- (NSData*)rsaEncryptData:(NSData*)data {

? ? SecKeyRef key = [self getPublicKey];

? ? size_t cipherBufferSize = SecKeyGetBlockSize(key);

? ? uint8_t *cipherBuffer = malloc(cipherBufferSize *sizeof(uint8_t));

? ? size_t blockSize = cipherBufferSize -11;

? ? ? size_t blockCount = (size_t)ceil([data length] / (double)blockSize);

? ? ? NSMutableData *encryptedData = [[NSMutableData alloc] init];

? ? for(inti=0; i

? ? unsigned longbufferSize = MIN(blockSize , [data length] - i * blockSize);

? ? NSData *buffer = [data subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];

? ? OSStatus status = SecKeyEncrypt(key, kSecPaddingPKCS1, (constuint8_t *)[buffer bytes], [buffer length], cipherBuffer, &cipherBufferSize);

? ? if(status != noErr) {

? ? ? ? return nil;

? ? }

? ? NSData *encryptedBytes = [[NSData alloc] initWithBytes:(constvoid*)cipherBuffer length:cipherBufferSize];

? ? [encryptedData appendData:encryptedBytes];

? ? }

? if (cipherBuffer){

? ? free(cipherBuffer);

? }

? return encryptedData;

? }

- (NSData*)rsaDecryptData:(NSData*)data {

SecKeyRef key = [self getPrivatKey];

size_t cipherBufferSize = SecKeyGetBlockSize(key);

size_t blockSize = cipherBufferSize;

size_t blockCount = (size_t)ceil([data length] / (double)blockSize);

NSMutableData *decryptedData = [[NSMutableData alloc] init];for(inti =0; i < blockCount; i++) {

? ? unsigned longbufferSize = MIN(blockSize , [data length] - i * blockSize);

? ? NSData *buffer = [data subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];

? ? size_t cipherLen = [buffer length];

? ? void*cipher = malloc(cipherLen);

? ? [buffer getBytes:cipher length:cipherLen];

? ? size_t plainLen = SecKeyGetBlockSize(key);

? ? void*plain = malloc(plainLen);

? ? OSStatus status = SecKeyDecrypt(key, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen);

? ? if(status != noErr) {

? ? ? ? return nil;

? ? }

? ? NSData *decryptedBytes = [[NSData alloc] initWithBytes:(constvoid*)plain length:plainLen];

? ? [decryptedData appendData:decryptedBytes];

}return decryptedData;

}


RSA加密中的Padding


RSA_PKCS1_PADDING 填充模式,最常用的模式

要求: 輸入:必須 比 RSA 鑰模長(zhǎng)(modulus) 短至少11個(gè)字節(jié), 也就是 RSA_size(rsa) – 11 如果輸入的明文過長(zhǎng),必須切割,然后填充。

輸出:和modulus一樣長(zhǎng)

根據(jù)這個(gè)要求,對(duì)于1024bit的密鑰,block length = 1024/8 – 11 = 117 字節(jié)

RSA_PKCS1_OAEP_PADDING

輸入:RSA_size(rsa) – 41

輸出:和modulus一樣長(zhǎng)

RSA_NO_PADDING  不填充

輸入:可以和RSA鑰模長(zhǎng)一樣長(zhǎng),如果輸入的明文過長(zhǎng),必須切割, 然后填充

輸出:和modulus一樣長(zhǎng)

簽名與驗(yàn)證

//對(duì)數(shù)據(jù)進(jìn)行sha256簽名

- (NSData *)rsaSHA256SignData:(NSData *)plainData {

? SecKeyRef key = [self getPrivatKey];

? size_t signedHashBytesSize = SecKeyGetBlockSize(key);

? uint8_t* signedHashBytes = malloc(signedHashBytesSize);

? memset(signedHashBytes, 0x0, signedHashBytesSize);

? size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;

? uint8_t* hashBytes = malloc(hashBytesSize);

? if(!CC_SHA256([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {

? ? return nil;

}

? ? ? SecKeyRawSign(key,

? ? ? ? ? ? ? kSecPaddingPKCS1SHA256,

? ? ? ? ? ? ? hashBytes,

? ? ? ? ? ? ? hashBytesSize,

? ? ? ? ? ? ? signedHashBytes,

? ? ? ? ? ? ? &signedHashBytesSize);

? ? NSData* signedHash = [NSData dataWithBytes:signedHashBytes

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? length:(NSUInteger)signedHashBytesSize];

? ? if (hashBytes)

? ? free(hashBytes);

? ? if (signedHashBytes)

? ? free(signedHashBytes);

? ? return signedHash;

? ? }


//這邊對(duì)簽名的數(shù)據(jù)進(jìn)行驗(yàn)證 驗(yàn)簽成功,則返回YES

- (BOOL)rsaSHA256VerifyData:(NSData *)plainData? ? withSignature:(NSData *)signature {

? ? SecKeyRef key = [self getPublicKey];

? ? size_t signedHashBytesSize = SecKeyGetBlockSize(key);

? ? constvoid* 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);

? ? returnstatus == errSecSuccess;

? ? }


文章到此就結(jié)束了,希望這篇文章對(duì)大家有所幫助。想看demo的請(qǐng)點(diǎn)擊:XYRSACryptor

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容