首页 > 解决方案 > 如何在 iOS 中解码 AES-128 数据

问题描述

我正在与需要加密的设备交换数据。根据说明,我的 iOS 应用程序生成一个 RSA 2048 位公钥-私钥对,然后我将公钥发送给设备。

我使用此处显示的 macOS 命令行创建了公钥-私钥对openssl(因为我无法弄清楚如何让 iOS 做到这一点 - 但这是一个未来的问题):

openssl req -x509 -newkey rsa:2048 -out cert.pem

openssl x509 -in cert.pem -noout -pubkey

cert.pem我将私钥和公钥中的值复制到我的应用程序中:

let certificate = "MIIDej....GWB"

let privateKey = "MIIFhz...Q=="

let publicKey = "MIIBI...AQAB"

当我向设备发送公钥时,设备很高兴并以 AES-128 格式发回使用我发送的公钥加密的数据。

我在这里不知所措,但我是试图让这个设备工作的人。

有没有办法获取我在我的应用程序中设置为 s 的私钥或证书String来解码来自设备的数据?

我一直在查看 Security 和 CryptoKit 文档,它让我头晕目眩。

FWIW,我能够使用文件SecCertificateCreateWithData中的字符串集cert.pem并读取它的一些信息,如摘要。但我不知道如何应用私钥或使用证书来解码数据。我需要像 Dummies 悬崖笔记之类的东西。

谢谢你。

标签: iosswiftsecurityopenssl

解决方案


Apple文档描述了如何在 iOS 端生成密钥对。

例子:

let tag = "com.example.keys.mykey".data(using: .utf8)!
let attributes: [String: Any] =
    [kSecAttrKeyType as String:            kSecAttrKeyTypeRSA,
     kSecAttrKeySizeInBits as String:      2048,
     kSecPrivateKeyAttrs as String:
        [kSecAttrIsPermanent as String:    true,
         kSecAttrApplicationTag as String: tag]
]

var publicKey: SecKey?
var privateKey: SecKey?
        
SecKeyGeneratePair(attributes, &publicKey, &privateKey)

更多属性在这里可用。

然后您可以使用方法获取私钥或公钥的外部表示: SecKeyCopyExternalRepresentation

例子:

var error: Unmanaged<CFError>?
SecKeyCopyExternalRepresentation(secKey, &error) as Data?

要解密 AES-128 数据,您需要使用CCCrypt. 在这里,您有来自 Apple 支持如何加密数据的示例,但要解密数据,您需要将第一个参数更改为kCCDecrypt.

例子:

extern NSData * SecDecryptAES128CBCPad(NSData * data, NSData * key, NSData * iv) {
    CCCryptorStatus    err;
    NSMutableData *    result;
    size_t              resultLength;

    NSCParameterAssert(key.length == kCCKeySizeAES128);
    NSCParameterAssert(iv.length == kCCBlockSizeAES128);

    // Padding can expand the data, so we have to allocate space for that.  The rule for block
    // cyphers, like AES, is that the padding only adds space on encryption (on decryption it
    // can reduce space, obviously, but we don't need to account for that) and it will only add
    // at most one block size worth of space.

    result = [[NSMutableData alloc] initWithLength:[data length] + kCCBlockSizeAES128];

    err = CCCrypt(
        kCCDecrypt,
        kCCAlgorithmAES128,
        kCCOptionPKCS7Padding,
        key.bytes, key.length,
        iv.bytes,
        data.bytes, data.length,
        result.mutableBytes,  result.length,
        &resultLength
    );
    assert(err == kCCSuccess);

    // Set the output length to the value returned by CCCrypt.  This is necessary because
    // we have padding enabled, meaning that we might have allocated more space than we needed.

    [result setLength:resultLength];

    return result;
}

方法中的参数CCCrypt(如kCCOptionPKCS7Padding, iv)您需要根据您的示例进行调整。


推荐阅读