Convert XML Dsig format to DER ASN.1 public key

后端 未结 1 1795
慢半拍i
慢半拍i 2021-01-03 16:21

I am working on an iPhone app that retrieves an RSA public key from an ASP.NET web service in the form:


  qdd0paiiBJ+xYaN4         


        
1条回答
  •  被撕碎了的回忆
    2021-01-03 16:45

    So, I used the SecKeyWrapper class to generate a random key, then used the -getPublicKeyBits method to get the binary representation of the public key (in whatever format is used internally). Presuming it is some form of DER ASN.1, I NSLog'd it to the console as hex and loaded it into this program. Sure enough, the internal representation is DER ASN.1, but it is a very simplified version of what I normally found for RSA key representations:

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

    Shouldn't be too tough to construct on the fly from a binary rep. of the modulus and exponent, since the DER encoding is just

    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)
    

    Here's my code, for simplicity. It uses a few Google libs for XML+base64, just heads up; also Apple's demo code SecKeyWrapper. See my other question for a note on making this work. Also, note that it is not ARC-compatible; this is left as an exercise for the reader (I wrote this years ago, now).

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

    0 讨论(0)
提交回复
热议问题