Domanda

Sto lavorando a un'app per iPhone che recupera una chiave pubblica RSA da un servizio Web ASP.NET nel modulo:

<RSAKeyValue>
  <Modulus>qdd0paiiBJ+xYaN4TKDdbEzrJJw9xlbRAltb5OPdegjLoW60yOjL/sni52WVsGC9QxpNitZR33dnUscmI0cTJoxkXypPjbD94UpH+p4el2tuKBypHlE7bERApuUp55y8BiRkbQNFH8smZFWDwtIc/PsJryeGf8fAryel8c5V3PU=</Modulus>
  <Exponent>AQAB</Exponent>
</RSAKeyValue>

Devo quindi convertire questa risposta in un NSData * del formato appropriato (da un intenso googling, molto probabilmente 'asn.1 der' formato binario. Ho il codice in atto per convertire entrambe le parti dalle loro rappresentazioni di base64 ai valori binari originali, ma non posso per la vita Di me capire un modo ragionevole per creare la chiave binaria monopezzo.

Il codice in attesa della chiave è il -addPeerPublicKey:(NSString *) keyBits:(NSData *) metodo del SecKeyWrapper classe da Apple CryptoExercise Esempio di progetto (codice qui).

Sarei più che felice di implementare questo altro modo-tutto ciò che ho bisogno è crittografare una singola stringa (nessuna decrittazione richiesta). Per quanto ne so, tuttavia, il framework di sicurezza integrato ha ciò di cui ho bisogno, se potessi solo colmare questo divario di formato. Se c'è un modo per convertire la chiave e inviarla codificata Base64 dal servizio Web, che funziona per me, ma non sono riuscito a trovare alcun modo per acconciarlo anche lì.

È stato utile?

Soluzione

Quindi, ho usato il SecKeyWrapper classe per generare una chiave casuale, quindi ha usato il -getPublicKeyBits Metodo per ottenere la rappresentazione binaria della chiave pubblica (in qualunque formato sia usato internamente). Presumendo che sia una qualche forma di der asn.1, l'ho fatto alla console come esadecimale e lo ha caricato questo programma. Abbastanza sicuro, la rappresentazione interna è der asn.1, ma è una versione molto semplificata di ciò che ho trovato normalmente per le rappresentazioni chiave RSA:

![SEQUENCE { INTEGER, INTEGER }][2]

Non dovrebbe essere troppo difficile per costruire al volo da un rappresentante binario. del modulo ed esponente, poiché la codifica DER è giusta

30 (for SEQUENCE) LL (total sequence byte length) 
02 (INTEGER) LL (modulus byte length) XX XX... (modulus data bytes) 
02 LL XX XX XX... (exponent length and bytes)

Ecco il mio codice, per semplicità. Utilizza alcune librerie Google per XML+Base64, si dirige verso l'alto; Anche il codice demo di Apple SeckeyWrapper. Vedere la mia altra domanda Per una nota su come fare questo lavoro. Inoltre, nota che lo è non Arco compatibile; Questo è rimasto come un esercizio per il lettore (ho scritto quest'anno, ora).

#define kTempPublicKey @"tempPayKey"
-(NSData *)encryptedDataWithXMLPublicKey:(NSString *)base64PublicKey data:(NSData *)data {
    if(![data length]){
        @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:@"Data not set." userInfo:nil];
    }
    GTMStringEncoding *base64 = [GTMStringEncoding rfc4648Base64StringEncoding];
    NSData *keyData = [base64 decode:base64PublicKey];
    NSError *err = nil;
    GDataXMLDocument *keyDoc = [[GDataXMLDocument alloc] initWithData:keyData options:0 error:&err];
    if(err){
        NSLog(@"Public key parse error: %@",err);
        [keyDoc release];
        return nil;
    }

    NSString *mod64 = [[[[keyDoc rootElement] elementsForName:@"Modulus"] lastObject] stringValue];
    NSString *exp64 = [[[[keyDoc rootElement] elementsForName:@"Exponent"] lastObject] stringValue];
    [keyDoc release];
    if(![mod64 length] || ![exp64 length]){
        @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:@"Malformed public key xml." userInfo:nil];
    }

    NSData *modBits = [base64 decode:mod64];
    NSData *expBits = [base64 decode:exp64];

    /* the following is my (bmosher) hack to hand-encode the mod and exp
     * into full DER encoding format, using the following as a guide:
     * http://luca.ntop.org/Teaching/Appunti/asn1.html
     * this is due to the unfortunate fact that the underlying API will
     * only accept this format (not the separate values)
     */

    // 6 extra bytes for tags and lengths
    NSMutableData *fullKey = [[NSMutableData alloc] initWithLength:6+[modBits length]+[expBits length]];
    unsigned char *fullKeyBytes = [fullKey mutableBytes];
    unsigned int bytep = 0; // current byte pointer
    fullKeyBytes[bytep++] = 0x30;
    if(4+[modBits length]+[expBits length] >= 128){
        fullKeyBytes[bytep++] = 0x81;
        [fullKey increaseLengthBy:1];
    }
    unsigned int seqLenLoc = bytep;
    fullKeyBytes[bytep++] = 4+[modBits length]+[expBits length];
    fullKeyBytes[bytep++] = 0x02;
    if([modBits length] >= 128){
        fullKeyBytes[bytep++] = 0x81;
        [fullKey increaseLengthBy:1];
        fullKeyBytes[seqLenLoc]++;
    }
    fullKeyBytes[bytep++] = [modBits length];
    [modBits getBytes:&fullKeyBytes[bytep]];
    bytep += [modBits length];
    fullKeyBytes[bytep++] = 0x02;
    fullKeyBytes[bytep++] = [expBits length];
    [expBits getBytes:&fullKeyBytes[bytep++]];

    SecKeyRef publicKey = [[SecKeyWrapper sharedWrapper] addPeerPublicKey:kTempPublicKey keyBits:fullKey];
    [fullKey release];

    NSData *encrypted = [[SecKeyWrapper sharedWrapper] wrapSymmetricKey:data keyRef:publicKey];
    // remove temporary key from keystore
    [[SecKeyWrapper sharedWrapper] removePeerPublicKey:kTempPublicKey];

    return encrypted;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top