【问题标题】:RSA encryption using SecKeyEncrypt gives error -4 (errSecUnimplemented)使用 SecKeyEncrypt 的 RSA 加密给出错误 -4 (errSecUnimplemented)
【发布时间】:2015-10-19 11:21:45
【问题描述】:

我正在尝试使用 iOS 上的安全框架通过 RSA 加密一些数据。我想加密一个简单的 base64 编码字符串,如下所示:

NSData *data = [[NSData alloc] initWithBase64EncodedString:@"aGFsbG8=" options:0x0];
NSData *encrypted = [pair encrypt:data];

pair 变量包含对在使用 SecKeyGeneratePair 之前成功生成的私钥和公钥的引用。

加密函数如下所示:

- (NSData *)encrypt:(NSData *)data {
    void *buffer = malloc([self blockSize] * sizeof(uint8_t));
    memset(buffer, 0x0, [self blockSize]);
    size_t ciphertextBufferLength = [data length];
    OSStatus res = SecKeyEncrypt([self keyRef], 0x1, [data bytes], [data length], &buffer[0], &ciphertextBufferLength);
    NSLog(@"Result of encryption: %d", res);
    return [NSData dataWithBytesNoCopy:buffer length:[self blockSize] freeWhenDone:YES];
}

[self blockSize] 的实现相当简单:

- (unsigned long)blockSize {
    return SecKeyGetBlockSize(keyRef);
}

我使用以下功能生成我的密钥:

- (BOOL)generateNewKeyPairOfSize:(unsigned int)keySize
{
    SecKeyRef privKey = [[self publicKey] keyRef];
    SecKeyRef pubKey = [[self publicKey] keyRef];

    NSDictionary *privateKeyDict = @{ (__bridge id)kSecAttrIsPermanent : @(YES), (__bridge id)kSecAttrApplicationTag : [[self privateKey] tag] };
    NSDictionary *publicKeyDict = @{ (__bridge id)kSecAttrIsPermanent : @(YES), (__bridge id)kSecAttrApplicationTag : [[self publicKey] tag] };
    NSDictionary *keyDict = @{ (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA, (__bridge id)kSecAttrKeySizeInBits : @(keySize), (__bridge id)kSecPublicKeyAttrs : publicKeyDict, (__bridge id)kSecPrivateKeyAttrs : privateKeyDict };
    OSStatus res = SecKeyGeneratePair((__bridge CFDictionaryRef)keyDict, &privKey, &pubKey);
    NSLog(@"Result of generating keys: %d", res);

    [[self publicKey] setKeyRef:pubKey];
    [[self privateKey] setKeyRef:privKey];

    return YES;
}

问题是res 的值是-4,根据文档,意思是errSecUnimplemented。我不确定我在这里做错了什么,因为我需要所有参数。我不确定参数是否有错误以及在哪里。调用[self blockSize] 返回128。

谁能帮我解决这个问题?

【问题讨论】:

  • 你能用 SecKeyGeneratePair() 显示你的密钥生成吗?
  • 我已经编辑了我的问题并添加了生成密钥的代码。

标签: ios security encryption cryptography rsa


【解决方案1】:

来自文档:

cipherTextLen - 输入时,提供的缓冲区大小 密文参数。返回时,实际放入的数据量 缓冲区。

您没有为ciphertextBufferLength 设置任何值。

更新 #1

SecKeyGeneratePair() 你有错误的参数:公钥参数必须是第一个,私钥是第二个。我认为这就是您出现错误代码 -4 的原因。

更新 #2

当您修复更新 #1 中的问题时,您将看到错误代码 -50 (errSecParam),因为您的密文长度错误。以下是正确加密/解密的样子:

[self generateNewKeyPairOfSize:1024];

NSData *data = [[NSData alloc] initWithBase64EncodedString:@"aGFsbG8=" options:0x0];

size_t cipherTextSize = [self blockSize];
uint8_t *cipherText = malloc(cipherTextSize);
memset(cipherText, 0, cipherTextSize);
OSStatus res = SecKeyEncrypt(_publicKey, kSecPaddingPKCS1, [data bytes], data.length, cipherText, &cipherTextSize);
NSLog(@"Result of encryption: %d", res);

size_t plainTextSize = cipherTextSize;
uint8_t *plainText = malloc(plainTextSize);
res = SecKeyDecrypt(_privateKey, kSecPaddingPKCS1, cipherText, cipherTextSize, plainText, &plainTextSize);
NSLog(@"Result of decryption: %d", res);

【讨论】:

  • 感谢您的回答。我已经初始化了ciphertextBufferLength 变量,但它仍然给我错误-4。我会更新我的答案。还有其他建议吗?
  • 它正在工作!感谢您的帮助。调试这些隐藏的错误真的很烦人。
  • 每次都以-4 失败。我认为您可以通过使其不正确来改进您的答案。
  • 好吧,这是警告。我试图使用私钥进行加密,但每次都会失败,因为没有公开解密密钥的加密是安全的,所以他们就是不让你这样做。
【解决方案2】:

除了上面的正确答案,为我解决的还有以下知识:

如果您尝试使用引用 私钥的 SecKeyRef 加密任何内容,您将得到 -4。

考虑一下。使用私钥加密的任何东西都不会是安全的,因为公钥是public。 /掌脸

是的,Apple 的框架做了负责任的事情,只是阻止您使用私钥加密某些内容。因为如果它允许你做那么愚蠢的事情,那么它会给你一种虚假的安全感,这是不负责任的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 2011-02-24
    • 2015-08-11
    • 1970-01-01
    • 2020-11-03
    • 2018-05-06
    相关资源
    最近更新 更多