将EC_KEY OpenSSL中的公钥和私钥导出到SecKeyRef

时间:2016-12-08 08:02:31

标签: ios objective-c c openssl keychain

我想从EC_KEY导出公钥和私钥,这是从OpenSSL创建的,我们知道EC_KEY保持密钥对,但openssl与将密钥对存储到安全区域不兼容。所以我想从OpenSSL创建证书并从那里创建密钥对,然后将密钥从EC_KEY导出到SecKeyRef,然后创建密钥对并存储在Secure Enclave中。

  • 首先,首先是这可能吗?
  • 如果是,那么如何从EC_KEY导出私人公钥并将其转换为SecRefKey
  • 如果我在接近时错了,那么请指导我一个

我从OpenSSL完成了第一部分从eliptic曲线EC_KEY创建的证书,并且还完成了最后一部分以创建Keypair。下面是创建Keypair的代码。

- (void)generateKeyPair:(NSUInteger)keySize {
OSStatus sanityCheck = noErr;
publicKey = NULL;
privateKey = NULL;

//  LOGGING_FACILITY1( keySize == 512 || keySize == 1024 || keySize == 2048, @"%d is an invalid and unsupported key size.", keySize );

// First delete current keys.
//  [self deleteAsymmetricKeys];

// Container dictionaries.
NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init];

// Set top level dictionary for the keypair.
[keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeEC forKey:(__bridge id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];

   [keyPairAttr setObject:(__bridge id)kSecAttrTokenID forKey:(__bridge id)kSecAttrTokenIDSecureEnclave];
//    [keyPairAttr setObject:(__bridge id)kSecAttrTokenID forKey:(__bridge id)kSecAttrTokenIDSecureEnclave];

// Set the private key dictionary.
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[privateKeyAttr setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag];

// See SecKey.h to set other flag values.

// Set the public key dictionary.
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
[publicKeyAttr setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
// See SecKey.h to set other flag values.

// Set attributes to top level dictionary.
[keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];

// SecKeyGeneratePair returns the SecKeyRefs just for educational purposes.
sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKey, &privateKey);

//  LOGGING_FACILITY( sanityCheck == noErr && publicKey != NULL && privateKey != NULL, @"Something really bad went wrong with generating the key pair." );
if(sanityCheck == noErr  && publicKey != NULL && privateKey != NULL)
{
    NSLog(@"Successful");
}

//  [privateKeyAttr release];
//  [publicKeyAttr release];
//  [keyPairAttr release];
}

1 个答案:

答案 0 :(得分:0)

您无法导入任何安全区域。您只能使用SecKeyGeneratePair生成密钥对(正如您在代码中所做的那样)

以下是Apple的文档中对此的引用:https://developer.apple.com/reference/security/keychain_services/token_id_values

生成后,您可以:

  • 签署数据(SecKeyRawSign
  • 验证签名(SecKeyRawVerify
  • 加密/解密(SecKeyCreateEncryptedDataSecKeyCreateDecryptedData
  • 取出钥匙(SecItemCopyMatching),随心所欲地做任何事情

如果你想与OpenSSL互操作,你只需要将它们转换成OpenSSL可以读取的东西(例如PEM,DER等)

这里是一个简单的公钥从原始字节转换(SecItemCopyMatching在kSecValueData下的字典中提供的内容)到PEM

+ (NSString*) openSSLPubKey:(NSData*) rawPublicKeyBytes {

  uint8_t curveOIDHeader[] = {0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00};

  NSMutableData* data = [[NSMutableData alloc] initWithBytes:curveOIDHeader length:26];

  [data appendData:rawPublicKeyBytes];

  NSString* base64EncodedString = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength | NSDataBase64EncodingEndLineWithCarriageReturn];
  return [NSString stringWithFormat:@"-----BEGIN PUBLIC KEY-----\n%@\n-----END PUBLIC KEY-----",base64EncodedString];

}

请注意,您只能在安全区域中存储256位椭圆曲线私钥,因此硬编码的OID标头