簡體   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