kSecAttrKeyTypeEC swift

北慕城南 提交于 2019-12-08 03:18:26

1) read please first https://www.apple.com/business/docs/iOS_Security_Guide.pdf 2) use generated ECDSA key for signing

import Foundation
import Security

private let kAsymmetricCryptoManagerApplicationTag = "com.AsymmetricCrypto.keypair"
private let kAsymmetricCryptoManagerKeyType = kSecAttrKeyTypeEC
private let kAsymmetricCryptoManagerKeySize = 384

// private key parameters
let privateKeyParams: [String: AnyObject] = [
    kSecAttrIsPermanent as String: false as AnyObject,
    kSecAttrApplicationTag as String: "com.AsymmetricCrypto.keypair" as AnyObject
]


// private key parameters
let publicKeyParams: [String: AnyObject] = [
    kSecAttrIsPermanent as String: false as AnyObject,
    kSecAttrApplicationTag as String: "com.AsymmetricCrypto.keypair" as AnyObject
]

// parameters
let parameters: [String: AnyObject] = [
    kSecAttrKeyType as String:          kAsymmetricCryptoManagerKeyType,
    kSecAttrKeySizeInBits as String:    kAsymmetricCryptoManagerKeySize as AnyObject,
    kSecPublicKeyAttrs as String:       publicKeyParams as AnyObject,
    kSecPrivateKeyAttrs as String:      privateKeyParams as AnyObject,
]

var pubKey, privKey: SecKey?
let status = SecKeyGeneratePair(parameters as CFDictionary, &pubKey, &privKey)

if let privKey = privKey, let pubKey = pubKey  {

    let message = "qwerty"
    let messageData = message
        .utf8CString
        .map{ UInt8(bitPattern: $0) }

    var sign = [UInt8](repeating: 0, count:  256)
    var length = sign.count

    let status = SecKeyRawSign(privKey, .PKCS1SHA384, messageData, messageData.count, &sign, &length)
    print("message: \"\(message)\" was sign with status:", status == errSecSuccess ? "OK": "KO")

    let verified = SecKeyRawVerify(pubKey, .PKCS1SHA384, messageData, messageData.count, sign, length)
    print("message: \"\(message)\" was", verified == errSecSuccess ? "unmodified\t" : "modified  \t", messageData)

    // modified messageData
    var modified = messageData
    modified[0] = messageData[0] + 1

    let modifiedMessage = String(cString: modified)

    let verified2 = SecKeyRawVerify(pubKey, .PKCS1SHA384, modified, modified.count, sign, length)
    print("message: \"\(modifiedMessage)\" was", verified2 == errSecSuccess ? "unmodified" : "modified  \t", modified)
}

it prints

message: "qwerty" was sign with status: OK
message: "qwerty" was unmodified     [113, 119, 101, 114, 116, 121, 0]
message: "rwerty" was modified       [114, 119, 101, 114, 116, 121, 0]

In real applications the

  • a) message is encrypted with some symmetric key (AES, ...)
  • b) the key is encrypted with RSA (SecKeyEncrypt)
  • c) encrypted message + encryptedKey are signed with ECDSA
  • d) everything is delivered to receiver
  • e) receiver check signature
  • f) decrypt encryptedKey (SecKeyDecrypt)
  • g) decrypt the message (AES, ...)

to check what is supported, use

SecKeyIsAlgorithmSupported(pubKey, .verify, .ecdsaSignatureRFC4754) == true

Another way to sign and verify data

if let cdata = CFDataCreate(kCFAllocatorDefault, messageData, messageData.count),
        // create signature
        let csign = SecKeyCreateSignature(privKey, .ecdsaSignatureRFC4754, cdata, nil) {

        // transfer messageData, csign

        // verify signature
        let verified = SecKeyVerifySignature(pubKey, .ecdsaSignatureRFC4754, cdata, csign, nil)
        print(cdata, csign, verified)
    }

For Encryption / Decryption use ECIES or RSA

SecKeyIsAlgorithmSupported(pubKey, .encrypt, .eciesEncryptionCofactorX963SHA384AESGCM)
SecKeyIsAlgorithmSupported(privKey, .decrypt, .eciesEncryptionCofactorX963SHA384AESGCM)

return true with your key pair. Encrypt / Decrypt with your key pair

if let cdata = CFDataCreate(kCFAllocatorDefault, messageData, messageData.count) {
        print("data", cdata)
        if let coded = SecKeyCreateEncryptedData(pubKey, .eciesEncryptionCofactorX963SHA384AESGCM, cdata, nil) {
            print("\ncoded",coded)

            if let decoded = SecKeyCreateDecryptedData(privKey, .eciesEncryptionCofactorX963SHA384AESGCM, coded, nil)
            {
                print("\ndecoded", decoded)
            }
        }
    }

prints

data <71776572 747900>

coded <04ebbf3a 4bb5b767 3251f4dc d131f7be 11516a92 4c8b4f66 23d08751 5ab45cc2 a97e908d 0e689e02 81b74ba0 f9181b24 5a90dea0 052ef3ef 4be6027d 1b67ab71 cf123561 4dfdac16 837f3b6c 195f5122 985bbedb 9dd2e52e e1828f08 4ce6ecb8 6b089205 c820bf0f f8dc6620 24fa53ed 75431006 a6f14c9d>

decoded <71776572 747900>

for more info read https://www.ietf.org/rfc/rfc5289.txt

So the answer is really simple..

Apple's implementation only supports ECDSA, which can be used for signing but not encryption.

errorStatus of -50 means your key size is too large. For a reference, look for "errSecKeySizeNotAllowed" here: https://www.osstatus.com/search/results?platform=all&framework=all&search=-50

Apples kSecAttrKeyTypeECSECPrimeRandom and kSecAttrKeyTypeEC only supports a key size of 256, inside and outside of the secure enclave, https://developer.apple.com/library/content/documentation/Security/Conceptual/CertKeyTrustProgGuide/SecureKeyGen.html, so you need to make the following change to work:

kAsymmetricCryptoManagerKeySize = 256

Larger key sizes are allowed for RSA, which is why you are not getting an error. A 256 bit EC key is said to be as secure as a 3072 bit RSA key.

Make sure you have added the "Security.framework" in your project under General > Linked Frameworks and Libraries.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!