Sto cercando di implementare un sistema in cui A genera una coppia di chiavi RSA e invia la chiave pubblica a B. B quindi genera una chiave AES e la crittografa utilizzando la chiave pubblica, inviando il risultato indietro A. Quindi decrittografa la chiave AES utilizzando la sua chiave privata RSA, crittografa i dati utilizzando il tasto AES e li invia a B, che può quindi decrittografarli utilizzando il tasto AES.Decifrazione RSA su Android - iPhone
Ho questo tutti lavorando sul lato Android, ma non riesco a ottenere il lato iPhone per giocare a palla (Sono nuovo di Objective C in modo che è probabilmente il motivo!)
Inizialmente, ero ottenere un errore 9809 quando si decodifica la chiave AES utilizzando la chiave privata RSA, che si traduce in errore in un errore generale. La ricerca dei punti di errore sul padding (sto usando PKCS1 Padding) è il problema, il passaggio a No Padding ha permesso al client iPhone di decodificare correttamente, ma la chiave decodificata AES è diversa da quella generata sul client Android.
L'obiettivo C è molto nuovo per me e sono sicuro che sto facendo un errore da scolaretto, qualcuno può indicarmi la direzione giusta per favore?
iPhone RSA generazione della coppia di chiavi
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;
Ricreare la chiave pubblica, generando la chiave AES e la crittografia su Android (notare il getBytes(...)
e getString(...)
basta fare qualche 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));
Decifrare la chiave AES su 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;
EDIT: Penso che ho ristretto questo giù un po ', il codice seguente dalla Decifrare la parte chiave AES del mio codice:
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);
produce il seguente output nella console:
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
occasionalmente tuttavia, essa esce con una dimensione di buffer cifrario di 256 come previsto e la decrittografia funziona perfettamente! So che mi manca qualcosa di ovvio?
* B genera quindi una chiave AES e la crittografa utilizzando la chiave pubblica, inviando il risultato a A *> Nota a margine: si è considerato che B firma i dati prima della crittografia? Come fa A sapere che la chiave è arrivata da B? –
Non so nulla di iPhone, ma sono scettico riguardo alcune delle vostre affermazioni. Cosa significa "Ho tutto questo lavorando sul lato Android"? Crittografare semplicemente senza generare un errore non significa che funzioni. Puoi decodificare correttamente anche sul lato Android? Inoltre, rimuovendo il requisito di imbottitura sul lato iPhone hai eliminato l'unico meccanismo che l'iPhone ha di rilevare un problema. Non restituisce un errore perché non ha modo di rilevare un errore.È ancora possibile che tutto e tutto sia errato. Lasciare attivata l'opzione di riempimento PKCS1. –
Il fatto che la rimozione del padding produca una chiave decifrata, che è sbagliato, suggerisce che i tuoi soldi qui. Non so nemmeno da dove iniziare a capire cosa c'è di sbagliato! Con "tutti quelli che lavorano sul lato Android" intendo che posso eseguire correttamente l'intero processo tra due dispositivi Android. –