iOS 5.0:生成x509大小为2048的rsa公钥是270字节而不是294字节。为什么?

时间:2015-06-04 16:13:11

标签: android ios rsa public-key-encryption encryption-asymmetric

我正在开发iOS 5的sdk,我正在通过套接字接口与设备进行通信。此设备需要发送一个大小为2048的base64编码的rsa x509公钥。

我使用以下代码生成密钥对:

OSStatus status = noErr;
NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary *publicKeyAttr= [[NSMutableDictionary alloc] init];
NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];

NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
                                    length:strlen((const char *)publicKeyIdentifier)];
NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier
                                     length:strlen((const char *)privateKeyIdentifier)];

SecKeyRef publicKey = NULL;
SecKeyRef privateKey = NULL;

[keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA
                forKey:(__bridge id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithInt:2048]
                forKey:(__bridge id)kSecAttrKeySizeInBits];

[privateKeyAttr setObject:[NSNumber numberWithBool:YES]
                   forKey:(__bridge id)kSecAttrIsPermanent];
[privateKeyAttr setObject:privateTag
                   forKey:(__bridge id)kSecAttrApplicationTag];

[publicKeyAttr setObject:[NSNumber numberWithBool:YES]
                  forKey:(__bridge id)kSecAttrIsPermanent];
[publicKeyAttr setObject:publicTag
                  forKey:(__bridge id)kSecAttrApplicationTag];

[keyPairAttr setObject:privateKeyAttr
                forKey:(__bridge id)kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr
                forKey:(__bridge id)kSecPublicKeyAttrs];

status = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr,
                            &_publicKey, &_privateKey);

然后我使用以下代码获取公钥的原始数据:

NSData* publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];

OSStatus sanityCheck = noErr;
NSData* publicKeyBits = nil;

NSMutableDictionary* queryPublicKey = [[NSMutableDictionary alloc] init];
[queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
[queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
[queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

// Temporarily add key to the Keychain, return as data:
NSMutableDictionary* attributes = [queryPublicKey mutableCopy];
[attributes setObject:(__bridge id)key forKey:(__bridge id)kSecValueRef];
[attributes setObject:@YES forKey:(__bridge id)kSecReturnData];
CFTypeRef result;
sanityCheck = SecItemAdd((__bridge CFDictionaryRef)attributes, &result);
if (sanityCheck == errSecSuccess) {
    publicKeyBits = CFBridgingRelease(result);

    // Remove from Keychain again:
    (void)SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);
}
return publicKeyBits;

以上代码为公钥产生 270字节长的NSData;我base64对这些数据进行编码并将其发送到设备,但它被拒绝了。

我的同事在工作中已完成对android的相同功能的实现,并按如下方式生成密钥对:

    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair key = kpg.generateKeyPair();

他使用:

    key.getPublic().getEncoded() 

访问 294字节长的公钥数据,以及设备接受的数据。

另外,如果我获取他生成的公钥的原始字节,并使用我的base64编码和发送,设备也会接受这个。

这有什么区别?为什么他的关键是294字节,而我的是270?我该如何解决这个问题?任何帮助将不胜感激。

修改

我刚刚找到https://crypto.stackexchange.com/questions/14491/why-is-a-2048-bit-public-rsa-key-represented-by-540-hexadecimal-characters-in-x,其中说明:

请注意,这不会计算“这是RSA公钥”的编码;这会占用额外的24个字节(包括开销)。

这听起来像我需要的,虽然我不知道如何包含这些信息。

任何?

1 个答案:

答案 0 :(得分:4)

以下是答案:http://blog.wingsofhermes.org/?p=42

"首先,当您从iPhone钥匙串导出密钥时,它会以缩减格式导出 - 只需公钥和指数,而不需要任何其他ASN.1内容编码的公钥。"

我认为这是这样的;我整天都在用显示器砸头。

血腥的苹果。