2015-06-04 111 views
0

我正在開發iOS 5的sdk工作,並且我正在通過套接字接口與設備進行通信。該設備需要被髮送大小的2048iOS 5.0:生成的x509大小爲2048的rsa公鑰是270字節而不是294字節。爲什麼?

我生成用下面的代碼密鑰對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個字節(包括開銷)。

這聽起來像我所需要的,但我不知道如何包含這些信息。

有人嗎?

+0

非常天真的觀察:基數64是64個可能性,即每個字節6位。所以一個294字節長的公鑰只有294 * 6 = 1764位的信息。你不需要至少342個字節來編碼基地64位的2048位數量嗎? – Tommy

+0

@Tommy這個問題與base64編碼無關,儘管我非常感謝你的迴應。 –

+0

是的,我完全誤讀了句子「上面的代碼產生公鑰長度爲270字節的NSData;我base64編碼這些數據並將其發送到設備,但它被拒絕。」在'產生270字節的NSData'步驟之前,在精神上放置base64步驟。 270個字節顯然適合2048位密鑰加上週圍的信息。 – Tommy

回答

3

這裏的答案:http://blog.wingsofhermes.org/?p=42

「首先,當你從iPhone鑰匙串中導出密鑰,它的出口在砍伐格式 - 只是公鑰和指數沒有任何的其他ASN.1東西你會期望在一個完全編碼的公鑰。「

我以爲是這樣的;我一整天都在盯着顯示器砸我的頭..

血腥的蘋果。

+0

正是我在找什麼。與作者一樣,如果有人能弄清楚如何做到這一點,我將非常感激。 – bgplaya

相關問題