用Swift生成base64 url​​编码的X.509格式的2048位RSA公钥?

在Apple Swift iOS上工作。 我必须为后端生成这个,因为它是一个安全的应用程序。

我是新来的安全和证书,一直在寻找一天,没有结果。

我怎样才能生成base64url编码的X.509格式2048位RSA公钥与swift?

任何帮助,高度赞赏。

在Swift中有一个用于处理公钥和私钥对的库,我最近创build的叫做Heimdall ,它允许你轻松地导出公钥的X.509格式的Base64string。

为了遵守SO规则,我也会在这个答案中包含实现(所以这是不言自明的)

public func X509PublicKey() -> NSString? { // Fetch the key, so that key = NSData of the public key let result = NSMutableData() let encodingLength: Int = { if key.length + 1 < 128 { return 1 } else { return ((key.length + 1) / 256) + 2 } }() let OID: [CUnsignedChar] = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00] var builder: [CUnsignedChar] = [] // ASN.1 SEQUENCE builder.append(0x30) // Overall size, made of OID + bitstring encoding + actual key let size = OID.count + 2 + encodingLength + key.length let encodedSize = encodeLength(size) builder.extend(encodedSize) result.appendBytes(builder, length: builder.count) result.appendBytes(OID, length: OID.count) builder.removeAll(keepCapacity: false) builder.append(0x03) builder.extend(encodeLength(key.length + 1)) builder.append(0x00) result.appendBytes(builder, length: builder.count) // Actual key bytes result.appendData(key) // Convert to Base64 and make safe for URLs var string = result.base64EncodedStringWithOptions(.allZeros) string = string.stringByReplacingOccurrencesOfString("/", withString: "_") string = string.stringByReplacingOccurrencesOfString("+", withString: "-") return string } public func encodeLength(length: Int) -> [CUnsignedChar] { if length < 128 { return [CUnsignedChar(length)]; } var i = (length / 256) + 1 var len = length var result: [CUnsignedChar] = [CUnsignedChar(i + 0x80)] for (var j = 0; j < i; j++) { result.insert(CUnsignedChar(len & 0xFF), atIndex: 1) len = len >> 8 } return result } 

我已经删除了数据获取代码,请参阅Heimdall或Jeff Hay的答案的来源

如果公钥已经在您的钥匙串中,则可以查找公钥并以base64的forms返回数据,其格式如下所示:

 // Create dictionary to specify attributes for the key we're // searching for. Swift will automatically bridge native values // to to right types for the SecItemCopyMatching() call. var queryAttrs = [NSString:AnyObject]() queryAttrs[kSecClass] = kSecClassKey queryAttrs[kSecAttrApplicationTag] = publicKeyTag queryAttrs[kSecAttrKeyType] = kSecAttrKeyTypeRSA queryAttrs[kSecReturnData] = true var publicKeyBits = Unmanaged<AnyObject>?() SecItemCopyMatching(queryAttrs, &publicKeyBits) // Work around a compiler bug with Unmanaged<AnyObject> types // the following two lines should simply be // let publicKeyData : NSData = publicKeyRef!.takeRetainedValue() as NSData let opaqueBits = publicKeyBits?.toOpaque() let publicKeyData = Unmanaged<NSData>.fromOpaque(opaqueBits).takeUnretainedValue() let publicKeyBase64 = publicKeyData.base64EncodedData(NSDataBase64EncodingOptions.Encoding64CharacterLineLength) 

如果您需要生成密钥对并将其存储在钥匙串中,请使用以下内容:

 // Create dictionaries to specify key attributes. Swift will // automatically bridge native values to to right types for the // SecKeyGeneratePair() call. var pairAttrs = [NSString:AnyObject]() var privateAttrs = [NSString:AnyObject]() var publicAttrs = [NSString:AnyObject]() privateAttrs[kSecAttrIsPermanent] = true privateAttrs[kSecAttrApplicationTag] = privateKeyTag publicAttrs[kSecAttrIsPermanent] = true publicAttrs[kSecAttrApplicationTag] = publicKeyTag pairAttrs[kSecAttrKeyType] = kSecAttrKeyTypeRSA pairAttrs[kSecAttrKeySizeInBits] = 2048 pairAttrs[(kSecPrivateKeyAttrs.takeUnretainedValue() as! String)] = privateAttrs pairAttrs[(kSecPublicKeyAttrs.takeUnretainedValue() as! String)] = publicAttrs var publicKeyPtr = Unmanaged<SecKey>?() var privateKeyPtr = Unmanaged<SecKey>?() let status = SecKeyGeneratePair(pairAttrs, &publicKeyPtr, &privateKeyPtr) 

注意: publicKeyTagprivateKeyTag是用于标识密钥库中的密钥的string。 苹果build议使用反向DNS表示法(com.company.key.xxx),但只要它们是唯一的,一切都应该是好的。

类似的问题与答案: 生成iPhone上的密钥对和打印logging为NSString

虽然在Objective-C中有答案,但Apple参考文献显示,函数(特别是最重要的一个SecKeyGeneratePair )也可以直接从Swift调用(只要可以从所有那些UnsafeMutablePointers等types转换)。