そのため、このSecKeyWrapper
クラスを使用してランダム キーを生成し、-getPublicKeyBits
メソッドを使用して公開キーのバイナリ表現を取得しました (内部で使用されている形式は何でも)。DER ASN.1 の何らかの形式であると仮定して、16 進数としてコンソールに NSLog し、このプログラムにロードしました。案の定、内部表現は 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 ライブラリを使用しています。また、Apple のデモ コード 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;
}