【发布时间】:2015-06-04 16:13:11
【问题描述】:
我正在为工作中的 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 字节?我该如何解决这个问题?任何帮助将不胜感激。
编辑
请注意,这不包括“这是一个 RSA 公钥”的编码;这会占用额外的 24 个字节(包括开销)。
这听起来像是我需要的,虽然我不知道如何包含这些信息。
有人吗?
【问题讨论】:
-
非常幼稚的观察:base 64 是 64 种可能性,即每个字节 6 位。所以一个 294 字节长的公钥只有 294*6 = 1764 位信息。您不应该至少需要 342 个字节来以 base 64 编码 2048 位数量吗?
-
@Tommy 这个问题与 base64 编码无关,尽管我非常感谢您的回复。
-
是的,我完全误读了这句话“上面的代码为公钥生成了 270 字节长的 NSData;我对这些数据进行了 base64 编码并将其发送到设备,但它被拒绝了。”精神上将base64步骤放在“产生270字节的NSData”步骤之前。 270 字节显然适合 2048 位密钥加上周围信息。
-
@DannyBravo 这么好的观点。我找到了我们跨国公司的 CEO,把你说的话告诉了他;愤怒的他改变了我们公司在大西洋两岸的整个发展过程。我想他也想为你提供一份首席分拣员的工作。
-
@JonSlater:虽然我很欣赏这个提议,但我必须恭敬地拒绝,因为我很满足于自雇。这很棒,真的。我可以优先考虑真正重要的事情,选择我想从事的工作,并且我可以避免必须支持 3 年前被 Apple 弃用的操作系统。顺便说一句,您可能想向您的跨国公司的 CEO 展示我在简单的 google 搜索中发现的以下统计数据,这可能会让他很好地了解他在支持只有 1% 的活跃操作系统上花费了多少时间和金钱用户,而不是专注于为许多人提供新功能。
标签: android ios rsa public-key-encryption encryption-asymmetric