簡體   English   中英

使用Swift生成base64 url​​編碼的X.509格式2048位RSA公鑰?

[英]Generate base64 url-encoded X.509 format 2048-bit RSA public key with Swift?

在Apple Swift for iOS中工作。 我必須為后端生成這個,因為它是一個安全的應用程序。

我是安全和證書的新手,現在一直在尋找一天沒有結果。

如何使用swift生成base64 url​​編碼的X.509格式2048位RSA公鑰?

任何幫助都非常感謝。

在我最近創建的一個名為Heimdall的 Swift中有一個用於處理公鑰 - 私鑰對的庫,它允許您輕松導出公鑰的X.509格式化Base64字符串。

為了遵守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返回,其內容類似於以下內容:

// 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是用於標識密鑰庫中密鑰的字符串。 Apple建議使用reverse-dns表示法(com.company.key.xxx),但只要它們是唯一的,一切都應該是好的。

回答類似的問題: 在iphone上生成密鑰對並打印為NSString

盡管在Objective-C中有答案, Apple參考文獻表明函數(尤其是最重要的函數SecKeyGeneratePair )也可以直接從Swift調用(只要你可以從所有那些UnsafeMutablePointers等進行類型轉換)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM