从swift中的模数和指数创建SecKey

时间:2014-11-25 17:24:13

标签: ios security swift seckeyref

我尝试用

创建自己的SecKey
exponent:
let exponent = "10001"

modulus: 
let modulus = "D6250B831F82EC984513922E797283E4D3879E1F0AD52364EBDA5A5696F6E75CDCE0704A993F3F95AA557A6882A525EC4B8344DA3E7DFDECCBACCEF18131E461D3C5D3D7E1334C6AE27E5CDEF8A577857542BCBEF6CF021B0EE5604534E6C6CBAEFA6EFFC1AB93DEE7CE51A8C8F2B7345680BDF840841C3A6F654CD1F10BA2FD5CA1C6E782A8FAEC79BD22FA12116D75FFAEDB2DEC151E0B60DB91F2E74BA78EFBB45DF739AF9CDD41C482DC22FC76E03C8E2141BDAE5406C0DA230E2C7EFFC68C8811E1544496332B03BCFF0F627A8DF51D2E2B32B0771D1C6F87AD56010DCB7A3862C63B88B2CF7D7AD40CC53AF0CFEC0820777C9CCE95A58848D67779AE8D"

as publicKey加密Swift中的文本。有人能帮我吗?

这是我的代码:

import Foundation
import Security

class Encryption {

var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?
var publicKey, privateKey: SecKey?
let parameters: [String:String] = [kSecAttrKeyType: kSecAttrKeyTypeRSA, kSecAttrKeySizeInBits: "2048"]

init(){

}

func genKey() {

    let status = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
    publicKey = publicKeyPtr!.takeRetainedValue()
    privateKey = privateKeyPtr!.takeRetainedValue()

}


func encrypt(plainText: String, publicKey: SecKey) -> [UInt8]{
    let blockSize = SecKeyGetBlockSize(publicKey)
    let plainTextData = [UInt8](plainText.utf8)
    let plainTextDataLength = UInt(countElements( plainText))
    var encryptedData = [UInt8](count: Int(blockSize), repeatedValue: 0)
    var encryptedDataLength = blockSize
    let result = SecKeyEncrypt(publicKey, SecPadding(kSecPaddingPKCS1),
        plainTextData, plainTextDataLength, &encryptedData, &encryptedDataLength)

    return encryptedData
}


func decrypt(data: [UInt8]) -> String{
    let blockSize = SecKeyGetBlockSize(publicKey)
    var decryptedData = [UInt8](count: Int(blockSize), repeatedValue: 0)
    var decryptedDataLength = blockSize
    let result = SecKeyDecrypt(privateKey, SecPadding(kSecPaddingPKCS1),
        data, blockSize,
        &decryptedData, &decryptedDataLength)

    let decryptedText = String(bytes: decryptedData,
        encoding:NSUTF8StringEncoding)

    return decryptedText!
}

}

2 个答案:

答案 0 :(得分:6)

对于仍在寻找答案的人,也许我可以提供帮助。

SecKeyCreateWithData

从iOS 10开始,您可以使用SecKeyCreateWithData从该密钥的外部表示中创建SecKey

此表示的格式应与SecKeyCopyExternalRepresentation返回的格式相同。正如docs中所讨论的那样,该格式是RSA密钥的PCKS#1。

因此,为了从给定的模数和指数创建SecKey,我们需要获得该密钥的PKCS#1表示。

引自PKCS#1

  

RSA公钥应使用ASN.1类型来表示   RSAPublicKey:

  RSAPublicKey ::= SEQUENCE {
      modulus           INTEGER,  -- n
      publicExponent    INTEGER   -- e
  }
     

RSAPublicKey类型的字段具有以下含义:

     
      
  • 模量是RSA模量n。
  •   
  • publicExponent是RSA公共指数e。
  •   

此ASN.1类型需要使用DER表示,以获取SecKeyCreateWithData期望的数据。

以正确的格式获取数据

下面我将尝试讨论如何在Swift中获得所需的数据格式。请注意,您也可以使用命令行中的OpenSSL执行此操作,如果您只需要执行一次,这可能会更容易。

Ignacio Nieto Carvajal在this article中详细介绍了需要做的事情。

基本上,您需要将模数和指数编码为DER INTEGER,然后将它们组合在DER SEQUENCE中。

您可以找到一些有关如何执行此操作的代码herehere。 ( Disclamer:我是该图书馆的贡献者之一。

我将在下面总结一下。

假设我们将RSA模数和公共指数作为字节数组。从模数和指数的不同表示中获取字节数组不应该太难。

let exponent: [UInt8] = [
    1, 0, 1
]

var modulus: [UInt8] = [
    136, 0, 243, 196, 194, 126, 151, 243, 72, 84, 246, 234, 207, 215, 168, 5, 233, 212, 8, 37, 34, 52, 215, 217, 223, 183, 58, 129, 66, 112, 88, 71, 201, 71, 33, 156, 132, 7, 189, 234, 110, 6, 46, 189, 233, 206, 61, 128, 220, 138, 56, 49, 34, 159, 245, 208, 214, 49, 169, 58, 170, 68, 127, 93, 137, 99, 74, 54, 65, 109, 112, 33, 65, 169, 246, 176, 128, 121, 171, 35, 214, 236, 210, 123, 94, 146, 86, 30, 134, 135, 116, 124, 4, 55, 208, 163, 219, 220, 203, 249, 107, 69, 147, 169, 66, 214, 179, 195, 152, 211, 209, 78, 100, 114, 209, 203, 120, 16, 254, 24, 39, 143, 79, 49, 202, 10, 37, 2, 155, 162, 14, 253, 194, 205, 74, 116, 60, 205, 25, 53, 85, 144, 72, 11, 7, 133, 78, 149, 111, 0, 215, 174, 36, 104, 175, 62, 196, 197, 49, 78, 172, 146, 82, 216, 160, 45, 48, 212, 50, 168, 208, 255, 205, 82, 22, 11, 13, 156, 197, 42, 159, 26, 124, 237, 178, 131, 239, 186, 37, 96, 24, 154, 243, 202, 252, 87, 102, 23, 19, 29, 73, 130, 95, 45, 219, 104, 13, 54, 30, 165, 144, 223, 1, 14, 169, 100, 111, 246, 54, 185, 47, 156, 238, 249, 88, 33, 244, 135, 233, 102, 36, 86, 196, 143, 178, 176, 62, 24, 178, 209, 163, 244, 116, 236, 81, 177, 190, 205, 140, 230, 6, 113, 158, 105, 111, 123
]

然后我们需要确保模数以0x00为前缀indicate that it is a non-negative number

modulus.insert(0x00, at: 0)

现在我们将模数和指数编码为INTEGERs

var modulusEncoded: [UInt8] = []
modulusEncoded.append(0x02)
modulusEncoded.append(contentsOf: lengthField(of: modulus))
modulusEncoded.append(contentsOf: modulus)

var exponentEncoded: [UInt8] = []
exponentEncoded.append(0x02)
exponentEncoded.append(contentsOf: lengthField(of: exponent))
exponentEncoded.append(contentsOf: exponent)

并将这些INTEGERs合并到SEQUENCE

var sequenceEncoded: [UInt8] = []
sequenceEncoded.append(0x30)
sequenceEncoded.append(contentsOf: lengthField(of: (modulusEncoded + exponentEncoded)))
sequenceEncoded.append(contentsOf: (modulusEncoded + exponentEncoded))

以下是一个辅助函数,用于计算上面使用的DER类型的长度字段:

func lengthField(of valueField: [UInt8]) -> [UInt8] {
    var count = valueField.count

    if count < 128 {
        return [ UInt8(count) ]
    }

    // The number of bytes needed to encode count.
    let lengthBytesCount = Int((log2(Double(count)) / 8) + 1)

    // The first byte in the length field encoding the number of remaining bytes.
    let firstLengthFieldByte = UInt8(128 + lengthBytesCount)

    var lengthField: [UInt8] = []
    for _ in 0..<lengthBytesCount {
        // Take the last 8 bits of count.
        let lengthByte = UInt8(count & 0xff)
        // Add them to the length field.
        lengthField.insert(lengthByte, at: 0)
        // Delete the last 8 bits of count.
        count = count >> 8
    }

    // Include the first byte.
    lengthField.insert(firstLengthFieldByte, at: 0)

    return lengthField
}

现在我们终于拥有了我们想要的数据。

let keyData = Data(bytes: sequenceEncoded)

您可以使用此数据创建SecKey

// RSA key size is the number of bits of the modulus.
let keySize = (modulus.count * 8)

let attributes: [String: Any] = [
    kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeySizeInBits as String: keySize
]

let publicKey = SecKeyCreateWithData(keyData as CFData, attributes as CFDictionary, nil)

我希望这有帮助!如果您需要更多信息,请与我们联系。

更多资源

答案 1 :(得分:0)

这是我创建RSA密钥对的方法,以防万一有人需要它。

//tuple type for public/private key pair at class level
typealias KeyPair = (publicKey: SecKey, privateKey: SecKey)

func generate() {


    // In your code block

    let publicKeyTag: String = "com.example.inc.public"
    let privateKeyTag: String = "com.example,inc.private"
    let keyPair = generateKeyPair(publicKeyTag, privateTag: privateKeyTag, keySize: 1024)
    var pbError:Unmanaged<CFError>?
    var prError:Unmanaged<CFError>?

    if #available(OSX 10.12, *) {
        guard let pbData = SecKeyCopyExternalRepresentation((keyPair?.publicKey)!, &pbError) as Data? else {
            print("error: ", pbError!.takeRetainedValue() as Error)
            return
        }

        guard let prData = SecKeyCopyExternalRepresentation((keyPair?.privateKey)!, &prError) as Data? else {
            print("private key error: ")
            return
        }

        print("Public: \(pbData.bytes)")
        print("Private: \(prData.bytes)")

        let strPublicKey = appendPrefixSuffixTo(pbData.base64EncodedString(options: .lineLength64Characters), prefix: "-----BEGIN RSA PUBLIC KEY-----\n", suffix: "\n-----END RSA PUBLIC KEY-----")
        print("public key: \n", strPublicKey)

        let strPrivateKey = appendPrefixSuffixTo(prData.base64EncodedString(options: .lineLength64Characters), prefix: "-----BEGIN RSA PRIVATE KEY-----\n", suffix: "\n-----END RSA PRIVATE KEY-----")
        print("private key: \n", strPrivateKey)


    } else {
        // Fallback on earlier versions
    }



}

func generateKeyPair(_ publicTag: String, privateTag: String, keySize: Int) -> KeyPair? {

    var publicKey, privateKey: SecKey?

    let publicKeyAttr: [NSObject: NSObject] = [
        kSecAttrIsPermanent:true as NSObject,
        kSecAttrApplicationTag:publicTag.data(using: String.Encoding.utf8)! as NSObject,
        kSecClass: kSecClassKey, // added this value
        kSecReturnData: kCFBooleanFalse] // added this value
    let privateKeyAttr: [NSObject: NSObject] = [
        kSecAttrIsPermanent:true as NSObject,
        kSecAttrApplicationTag:privateTag.data(using: String.Encoding.utf8)! as NSObject,
        kSecClass: kSecClassKey, // added this value
        kSecReturnData: kCFBooleanFalse] // added this value


    var keyPairAttr = [NSObject: Any]()
    keyPairAttr[kSecAttrType] = kSecAttrKeyTypeRSA
    keyPairAttr[kSecAttrKeySizeInBits] = 1024
    keyPairAttr[kSecReturnData] = true
    keyPairAttr[kSecPublicKeyAttrs] = publicKeyAttr as NSObject
    keyPairAttr[kSecPrivateKeyAttrs] = privateKeyAttr as NSObject


    if SecKeyGeneratePair(keyPairAttr as CFDictionary, &publicKey, &privateKey) == 0 {
        print("RSA key pair generation Successful")
        return KeyPair(publicKey: publicKey!, privateKey: privateKey!)
    }

    return nil

}




func appendPrefixSuffixTo(_ string: String, prefix: String, suffix: String) -> String {
    return "\(prefix)\(string)\(suffix)"
}