2015-04-07 6 views

Antwort

4

Es gibt eine Bibliothek für die Behandlung von öffentlich-privaten Schlüsselpaaren in Swift, die ich kürzlich erstellt habe, Heimdall, mit der Sie die X.509-formatierte Base64-Zeichenfolge des öffentlichen Schlüssels einfach exportieren können.

mit SO Regeln einzuhalten, werde ich auch die Umsetzung in dieser Antwort sind (so dass sie selbsterklärend)

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 
} 

ich die Daten-Abruf Code entfernt haben, entweder Quelle beziehen von Heimdall oder Jeff Hay's answer

4

Wenn der öffentliche Schlüssel bereits in Ihrem Schlüsselbund ist, können Sie den öffentlichen Schlüssel suchen und geben die Daten als Base64 mit etwas ähnlich der folgenden:

// 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) 

Wenn Sie das Schlüsselpaar und Speicher zu erzeugen, brauchen es in dem Schlüsselbund, verwenden sie etwas in diese Richtung:

// 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) 

Hinweis:publicKeyTag und privateKeyTag Strings verwendet, um den Schlüssel im Schlüsselspeicher zu identifizieren. Apple empfiehlt umgekehrte DNS-Notation (com.company.key.xxx), aber solange sie eindeutig sind, sollten alle gut sein.

Verwandte Themen