简体   繁体   English

将XML Dsig格式转换为DER ASN.1公钥

[英]Convert XML Dsig format to DER ASN.1 public key

I am working on an iPhone app that retrieves an RSA public key from an ASP.NET web service in the form: 我正在使用一个iPhone应用程序,该应用程序以以下形式从ASP.NET Web服务检索RSA公钥:

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

I need to then convert this response into an NSData * of the appropriate format (from some intense Googling, most likely 'ASN.1 DER' binary format. I've got code in place to convert both parts from their Base64 representations to the original binary values, but I can't for the life of me figure out a reasonable way to create the one-piece binary key. 然后,我需要将此响应转换为适当格式的NSData * (来自某种密集的谷歌搜索,最有可能是“ ASN.1 DER”二进制格式。我已经准备好了将两部分从其Base64表示形式转换为原始形式的代码二进制值,但我无法终生想出一种合理的方式来创建整体式二进制密钥。

The code waiting for the key is the -addPeerPublicKey:(NSString *) keyBits:(NSData *) method of the SecKeyWrapper class from Apple's CryptoExercise example project (Code here ). 等待密钥的代码是Apple的CryptoExercise示例项目的SecKeyWrapper类的-addPeerPublicKey:(NSString *) keyBits:(NSData *)方法(代码在此处 )。

I would be more than happy to implement this another way--all I need is to encrypt a single string (no decryption required). 我将很乐意以另一种方式实现这一点-我所需要的只是加密单个字符串(无需解密)。 As far as I can tell, though, the built-in Security framework has what I need, if I could just close this format gap. 据我所知,内置安全框架具有我所需要的,如果我能缩小这种格式差距的话。 If there is a way to convert the key and send it Base64-encoded from the webservice, that works for me as well--but I couldn't find any way to ASN.1-encode it there, either. 如果有一种方法可以转换密钥并从Web服务发送以Base64编码的密钥,那对我也同样适用-但我也找不到任何方法来对ASN.1进行编码。

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). 因此,我使用SecKeyWrapper类生成随机密钥,然后使用-getPublicKeyBits方法获取公共密钥的二进制表示形式(内部使用的任何格式)。 Presuming it is some form of DER ASN.1, I NSLog'd it to the console as hex and loaded it into this program . 假设它是某种形式的DER ASN.1,我将其以十六进制形式登录到控制台,然后将其加载到该程序中 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: 当然,内部表示形式是DER ASN.1,但这是我通常在RSA密钥表示形式中找到的非常简化的版本:

![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 因为DER编码只是

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; 它使用了一些针对XML + base64的Google库,只是请注意; also Apple's demo code SecKeyWrapper. 还有苹果的演示代码SecKeyWrapper。 See my other question for a note on making this work. 请参阅我的其他问题 ,以获取有关进行此工作的注释。 Also, note that it is not ARC-compatible; 此外,请注意,这不是 ARC兼容; 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM