繁体   English   中英

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

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

我正在使用一个iPhone应用程序,该应用程序以以下形式从ASP.NET Web服务检索RSA公钥:

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

然后,我需要将此响应转换为适当格式的NSData * (来自某种密集的谷歌搜索,最有可能是“ ASN.1 DER”二进制格式。我已经准备好了将两部分从其Base64表示形式转换为原始形式的代码二进制值,但我无法终生想出一种合理的方式来创建整体式二进制密钥。

等待密钥的代码是Apple的CryptoExercise示例项目的SecKeyWrapper类的-addPeerPublicKey:(NSString *) keyBits:(NSData *)方法(代码在此处 )。

我将很乐意以另一种方式实现这一点-我所需要的只是加密单个字符串(无需解密)。 据我所知,内置安全框架具有我所需要的,如果我能缩小这种格式差距的话。 如果有一种方法可以转换密钥并从Web服务发送以Base64编码的密钥,那对我也同样适用-但我也找不到任何方法来对ASN.1进行编码。

因此,我使用SecKeyWrapper类生成随机密钥,然后使用-getPublicKeyBits方法获取公共密钥的二进制表示形式(内部使用的任何格式)。 假设它是某种形式的DER ASN.1,我将其以十六进制形式登录到控制台,然后将其加载到该程序中 当然,内部表示形式是DER ASN.1,但这是我通常在RSA密钥表示形式中找到的非常简化的版本:

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

从二进制表示中即时构建应该不会太困难。 因为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)

为了简单起见,这是我的代码。 它使用了一些针对XML + base64的Google库,只是请注意; 还有苹果的演示代码SecKeyWrapper。 请参阅我的其他问题 ,以获取有关进行此工作的注释。 此外,请注意,这不是 ARC兼容; 这留给读者练习(我几年前写过,现在)。

#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