简体   繁体   English

如何在 macOS 上使用 Security.framework 解密数据?

[英]How to decrypt data with Security.framework on macOS?

I need to decrypt data with a RSA public key on macOS , by googling I know we can use method SecKeyCreateDecryptedData of Security.framework to achieve that, but it leads to two problems:我需要在macOS上使用 RSA public解密数据,通过谷歌搜索我知道我们可以使用Security.framework的方法SecKeyCreateDecryptedData来实现这一点,但这会导致两个问题:

  1. SecKeyCreateDecryptedData accepts a private key to execute decryption, but in my situation, the data is encrypted with private key in the server-end, and needs to be decrypted with public key in the client-end. SecKeyCreateDecryptedData接受private执行解密,但在我的情况下,数据在服务器端用私钥加密,需要在客户端用public解密。

  2. I tried to create SecKey from a RSA public key string, but failed.我试图从 RSA public字符串创建SecKey ,但失败了。

My code:我的代码:

import Foundation
 
func getPublicKey(from data: Data) throws -> SecKey {
    var error: Unmanaged<CFError>? = nil
    let publicKeyMaybe = SecKeyCreateWithData(
        data as NSData,
        [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeyClass: kSecAttrKeyClassPublic
        ] as NSDictionary,
        &error)
    guard let publicKey = publicKeyMaybe else {
        throw error!.takeRetainedValue() as Error
    }
    return publicKey
}

func decrypt(key: SecKey, data cipherTextData: Data) -> Data? {
    let algorithm: SecKeyAlgorithm = .eciesEncryptionCofactorVariableIVX963SHA256AESGCM
    guard SecKeyIsAlgorithmSupported(key, .decrypt, algorithm) else {
        print("Can't decrypt. Algorithm not supported.")
        return nil
    }

    var error: Unmanaged<CFError>? = nil
    let clearTextData = SecKeyCreateDecryptedData(key,
                                                  algorithm,
                                                  cipherTextData as CFData,
                                                  &error) as Data?
    if let error = error {
        print("Can't decrypt. %@", (error.takeRetainedValue() as Error).localizedDescription)
        return nil
    }
    guard clearTextData != nil else {
        print("Can't decrypt. No resulting cleartextData.")
        return nil
    }
    print("Decrypted data.")
    return clearTextData
}

func testDecrypt() {
    let rawString = "0ed3a2c57f5dEJgqXT9760269b8cc5cd76f3afcf"
    let decodedData = Data.init(base64Encoded: rawString, options: [])!

    let pubKey = try! getPublicKey(from: kPubKey.data(using: .utf8)!) // Error: RSA public key creation from data failed
    let decryptedData = decrypt(key: pubKey, data: decodedData)!
    let decrypted = String.init(data: decryptedData, encoding: .utf8)!

    print(">>>>>>> decrypted string: \(decrypted)")
}

testDecrypt()

With method of Kazunori Takaishi , I tested all the algorithm, none of them is supported:Kazunori Takaishi的方法,我测试了所有的算法,都不支持:

func decrypt(key: SecKey, data cipherTextData: Data) -> Data? {
        let algorithms: [SecKeyAlgorithm] = [
            .rsaSignatureRaw,
            .rsaSignatureDigestPKCS1v15Raw,
            .rsaSignatureDigestPKCS1v15SHA1,
            .rsaSignatureDigestPKCS1v15SHA224,
            .rsaSignatureDigestPKCS1v15SHA256,
            .rsaSignatureDigestPKCS1v15SHA384,
            .rsaSignatureDigestPKCS1v15SHA512,
            .rsaSignatureMessagePKCS1v15SHA1,
            .rsaSignatureMessagePKCS1v15SHA224,
            .rsaSignatureMessagePKCS1v15SHA256,
            .rsaSignatureMessagePKCS1v15SHA384,
            .rsaSignatureMessagePKCS1v15SHA512,
            .rsaSignatureDigestPSSSHA1,
            .rsaSignatureDigestPSSSHA224,
            .rsaSignatureDigestPSSSHA256,
            .rsaSignatureDigestPSSSHA384,
            .rsaSignatureDigestPSSSHA512,
            .rsaSignatureMessagePSSSHA1,
            .rsaSignatureMessagePSSSHA224,
            .rsaSignatureMessagePSSSHA256,
            .rsaSignatureMessagePSSSHA384,
            .rsaSignatureMessagePSSSHA512,
            .ecdsaSignatureRFC4754,
            .ecdsaSignatureDigestX962,
            .ecdsaSignatureDigestX962SHA1,
            .ecdsaSignatureDigestX962SHA224,
            .ecdsaSignatureDigestX962SHA256,
            .ecdsaSignatureDigestX962SHA384,
            .ecdsaSignatureDigestX962SHA512,
            .ecdsaSignatureMessageX962SHA1,
            .ecdsaSignatureMessageX962SHA224,
            .ecdsaSignatureMessageX962SHA256,
            .ecdsaSignatureMessageX962SHA384,
            .ecdsaSignatureMessageX962SHA512,
            .rsaEncryptionRaw,
            .rsaEncryptionPKCS1,
            .rsaEncryptionOAEPSHA1,
            .rsaEncryptionOAEPSHA224,
            .rsaEncryptionOAEPSHA256,
            .rsaEncryptionOAEPSHA384,
            .rsaEncryptionOAEPSHA512,
            .rsaEncryptionOAEPSHA1AESGCM,
            .rsaEncryptionOAEPSHA224AESGCM,
            .rsaEncryptionOAEPSHA256AESGCM,
            .rsaEncryptionOAEPSHA384AESGCM,
            .rsaEncryptionOAEPSHA512AESGCM,
            .eciesEncryptionStandardX963SHA1AESGCM,
            .eciesEncryptionStandardX963SHA224AESGCM,
            .eciesEncryptionStandardX963SHA256AESGCM,
            .eciesEncryptionStandardX963SHA384AESGCM,
            .eciesEncryptionStandardX963SHA512AESGCM,
            .eciesEncryptionCofactorX963SHA1AESGCM,
            .eciesEncryptionCofactorX963SHA224AESGCM,
            .eciesEncryptionCofactorX963SHA256AESGCM,
            .eciesEncryptionCofactorX963SHA384AESGCM,
            .eciesEncryptionCofactorX963SHA512AESGCM,
            .eciesEncryptionStandardVariableIVX963SHA224AESGCM,
            .eciesEncryptionStandardVariableIVX963SHA256AESGCM,
            .eciesEncryptionStandardVariableIVX963SHA384AESGCM,
            .eciesEncryptionStandardVariableIVX963SHA512AESGCM,
            .eciesEncryptionCofactorVariableIVX963SHA224AESGCM,
            .eciesEncryptionCofactorVariableIVX963SHA256AESGCM,
            .eciesEncryptionCofactorVariableIVX963SHA384AESGCM,
            .eciesEncryptionCofactorVariableIVX963SHA512AESGCM,
            .ecdhKeyExchangeStandard,
            .ecdhKeyExchangeStandardX963SHA1,
            .ecdhKeyExchangeStandardX963SHA224,
            .ecdhKeyExchangeStandardX963SHA256,
            .ecdhKeyExchangeStandardX963SHA384,
            .ecdhKeyExchangeStandardX963SHA512,
            .ecdhKeyExchangeCofactor,
            .ecdhKeyExchangeCofactorX963SHA1,
            .ecdhKeyExchangeCofactorX963SHA224,
            .ecdhKeyExchangeCofactorX963SHA256,
            .ecdhKeyExchangeCofactorX963SHA384,
            .ecdhKeyExchangeCofactorX963SHA512
        ]
        
        for a in algorithms {
            if SecKeyIsAlgorithmSupported(key, .decrypt, a) {
                print(">>>>>>>>>>>>> supported algorithm: \(a)")
            }
        }
        
        //==================
        
        let algorithm: SecKeyAlgorithm = .rsaEncryptionPKCS1 // .rsaSignatureMessagePKCS1v15SHA256 // .rsaSignatureDigestPKCS1v15SHA1 // .rsaSignatureDigestPKCS1v15Raw // .rsaSignatureDigestPKCS1v15SHA256 //.rsaEncryptionPKCS1
        
//        guard SecKeyIsAlgorithmSupported(key, .decrypt, algorithm) else {
//            print("Can't decrypt. Algorithm not supported.")
//            return nil
//        }

        var error: Unmanaged<CFError>? = nil
        let clearTextData = SecKeyCreateDecryptedData(key,
                                                      algorithm,
                                                      cipherTextData as CFData,
                                                      &error) as Data?
        if let error = error {
            print("Can't decrypt. \((error.takeRetainedValue() as Error).localizedDescription)")
            return nil
        }
        guard clearTextData != nil else {
            print("Can't decrypt. No resulting cleartextData.")
            return nil
        }
        print("Decrypted data.")
        return clearTextData
    }

If your code only works on Mac OS, you may be able to create a Seckey by using the SecKeyCreateFromData method instead of the SecKeyCreateWithData method.如果您的代码仅适用于 Mac OS,您可以使用SecKeyCreateFromData方法而不是SecKeyCreateWithData方法来创建Seckey

Here is Sample Code:这是示例代码:

    func getPublicKey(from data: Data?) throws -> SecKey {
        var error: Unmanaged<CFError>? = nil
        guard let data = data else { throw error!.takeRetainedValue() as Error }
        let publicKeyMaybe = SecKeyCreateFromData([:] as CFDictionary, data as NSData, &error)
        guard let publicKey = publicKeyMaybe else {
            throw error!.takeRetainedValue() as Error
        }
        return publicKey
    }

And You should convert RSA public key string to data using ASCII encoding.并且您应该使用ASCII编码将RSA公钥字符串转换为数据。

let pubKey = try! getPublicKey(from: kPubKey.data(using: .ascii))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM