我試圖實現一個系統,其中A生成一個RSA密鑰對並將公鑰發送給B. B然後生成一個AES密鑰並使用公鑰將其加密,發回結果然後使用其RSA私鑰對AES密鑰進行解密,然後使用AES密鑰對數據進行加密並將其發送給B,B可以使用AES密鑰將其解密。在Android的RSA解密 - iPhone
我已經得到了這一切在Android方面的工作,但我不能拿到iPhone一邊玩球(我新的目標C,使這可能是爲什麼!)
起初,我很使用RSA私鑰解密AES密鑰時得到錯誤9809,這無益地轉化爲一般錯誤。研究填充(我使用PKCS1填充)的錯誤點是問題,切換到無填充允許iPhone客戶端解密成功,但解密的AES密鑰與Android客戶端上生成的不同。
目標C對我來說很新,我敢肯定我只是犯了一個小學生的錯誤,任何人都可以將我指向正確的方向嗎?
iPhone RSA密鑰對生成
static const unsigned char _encodedRSAEncryptionOID[15] = {
/* Sequence of length 0xd made up of OID followed by NULL */
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00
};
NSData * publicTag = [publicKeyIdentifier dataUsingEncoding:NSUTF8StringEncoding];
// Now lets extract the public key - build query to get bits
NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(__bridge id) kSecClassKey
forKey:(__bridge id) kSecClass];
[queryPublicKey setObject:publicTag
forKey:(__bridge id) kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id) kSecAttrKeyTypeRSA
forKey:(__bridge id) kSecAttrKeyType];
[queryPublicKey setObject:[NSNumber numberWithBool:YES]
forKey:(__bridge id) kSecReturnData];
CFTypeRef pk;
OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &pk);
NSData* publicKeyBits = (__bridge_transfer NSData*)pk;
if (err != noErr) {
return nil;
}
// OK - that gives us the "BITSTRING component of a full DER
// encoded RSA public key - we now need to build the rest
unsigned char builder[15];
NSMutableData * encKey = [[NSMutableData alloc] init];
int bitstringEncLength;
// When we get to the bitstring - how will we encode it?
if ([publicKeyBits length ] + 1 < 128)
bitstringEncLength = 1 ;
else
bitstringEncLength = (([publicKeyBits length ] +1)/256) + 2 ;
// Overall we have a sequence of a certain length
builder[0] = 0x30; // ASN.1 encoding representing a SEQUENCE
// Build up overall size made up of -
// size of OID + size of bitstring encoding + size of actual key
size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength +
[publicKeyBits length];
size_t j = encodeLength(&builder[1], i);
[encKey appendBytes:builder length:j +1];
// First part of the sequence is the OID
[encKey appendBytes:_encodedRSAEncryptionOID
length:sizeof(_encodedRSAEncryptionOID)];
// Now add the bitstring
builder[0] = 0x03;
j = encodeLength(&builder[1], [publicKeyBits length] + 1);
builder[j+1] = 0x00;
[encKey appendBytes:builder length:j + 2];
// Now the actual key
[encKey appendData:publicKeyBits];
// Now translate the result to a Base64 string
Base64* base64 = [[Base64 alloc] init];
NSString* ret = [base64 encode:encKey];
return ret;
重新創建公共密鑰,生成AES密鑰,它在Android 加密(注意getBytes(...)
和getString(...)
只是做了一些的base64 encoding.decoding )
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256, new SecureRandom());
SecretKey secretKey = keyGen.generateKey();
byte[] publicKeyBytes = getBytes(publicKey.getKey());
PublicKey rsaKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.ENCRYPT_MODE, rsaKey);
String keyEncoded = getString(key);
return getString(encryptedKeyBytes));
解密AES密鑰iPhone上
Base64* base64 = [[Base64 alloc] init];
NSData* cipherText = [base64 decode:textBase64];
const uint8_t *cipherBuffer = (const uint8_t*)[cipherText bytes];
size_t cipherBufferSize = strlen((char *) cipherBuffer);
uint8_t *plainBuffer = (uint8_t *)calloc(SecKeyGetBlockSize(publicKey), sizeof(uint8_t));
size_t plainBufferSize = SecKeyGetBlockSize(publicKey);
OSStatus status = SecKeyDecrypt(privateKey,
kSecPaddingPKCS1,
&cipherBuffer[0],
cipherBufferSize,
&plainBuffer[0],
&plainBufferSize
);
NSData* finalData = [[NSData alloc] initWithBytes:plainBuffer length:plainBufferSize];
NSString *result = [base64 encode:finalData];
return result;
編輯:我想我已經縮小下來一點,從我的代碼解密AES密鑰部分下面的代碼:
NSData* cipherText = [base64 decode:text];
NSLog(@"cipherText %@", cipherText);
const uint8_t *cipherBuffer = (const uint8_t*)[cipherText bytes];
NSLog(@"cipherBuffer %s", cipherBuffer);
size_t cipherBufferSize = strlen((char *) cipherBuffer);
NSLog(@"cipherBufferSize %zd", cipherBufferSize);
可生產在控制檯下面的輸出:
cipherText <31226275 cc56069a e96b7f6f 0fbee853 32d07de6 436755c9 e27b88a6 04176947 d57f7108 de68e5b8 49595e9f 09bceb30 1d615927 c205f205 eb644fa7 bff6c02b 885605de eb5bd4ee 473bb4d3 df768017 24552706 ea67f347 2952614e ad63f3c6 eb0022d3 a0513afa 0e59ba63 cb5c9787 a40ecad4 a866fdc7 26b60cc2 088a3499 a84c0595 fb1c2be8 5c85b88d 7856b4bd 655f6fec 905ca221 d6bb03c0 7329410b b235ef8f 1ef97a64 7fabb280 90118ff7 4b1e91f6 162134fc 5cbf962e 813e39e7 993b0fb9 e3c4b30c ef6a7b90 9d64c41a 1211ab34 c2c52235 d2ec3b65 d1314cee 70eafe65 f4a6c5e4 660cf889 4540a784 d14cc5a8 49a12c43 c76f7f03 5fbcd44f>
cipherBuffer 1"buÃVöÈkoæËS2–}ÊCgU…‚{à¶iG’qfihÂ∏IY^ü ºÎ0aY'¬ÚÎdOßøˆ¿+àVfiÎ[‘ÓG;¥」flvÄ$U'ÍgÛG)RaN≠cÛ∆Î
cipherBufferSize 97
偶爾但是,它出來用256密緩衝區大小如預期和解密完美的作品!我知道我必須失去一些明顯的東西?
* B然後生成一個AES密鑰並使用公鑰對其進行加密,並將結果發送回A *>附註 - 是否考慮讓B在加密之前對數據進行簽名? A如何知道密鑰來自B? –
我對iPhone一無所知,但我對你的一些言論持懷疑態度。 「我已經在Android這方面有所作爲」是什麼意思?簡單地加密而不產生錯誤並不意味着它正在工作。你也可以在Android端正確解密嗎?另外,通過消除iPhone側的填充要求,您已經消除了iPhone檢測問題的唯一機制。它不會返回錯誤,因爲它無法檢測到錯誤。任何事情都是不正確的。打開PKCS1填充選項。 –
刪除填充產生一個解密密鑰這就是錯誤的事實表明你在這裏的錢。我甚至不知道從哪裏開始解決什麼是錯的! 「所有在Android方面工作」我的意思是我可以在兩個Android設備之間正確執行整個過程。 –