为什么SecKeyEncrypt会为超过246字节的输入字符串返回paramErr(-50)?

时间:2013-01-09 23:58:09

标签: ios public-key-encryption

我正在使用带有JSON格式字符串的SecKeyEncrypt作为输入。如果传递SecKeyEncrypt一个plainTextLength小于246,它就可以了。如果我传递的长度为246或更长,则失败并返回值为paramErr (-50)

这可能是字符串本身的问题。我发送SecKeyEncrypt的一个例子是:

{"handle":"music-list","sym_key":"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALeaEO7ZrjgOFGLBzBHZtQuzH2GNDYMLWP+fIFNu5Y+59C6HECY+jt0yOXXom2mzp/WYYI/9G+Ig8OD6YiKv2nMCAwEAAQ==","app_id":"xgfdt.LibraryTestApp","api_key":"7e080f74de3625b90dd293fc8be560a5cdfafc08"}

第245个字符为'0'。

在此工作之间切换的唯一输入是plainTextLength。 SecKeyGetBlockSize()向我返回256,因此任何长达256个字符的输入都应该有效。

这是我的加密方法:

+ (NSData*)encrypt:(NSString*)data usingPublicKeyWithTag:(NSString*)tag
{

    OSStatus status = noErr;

    size_t cipherBufferSize;
    uint8_t *cipherBuffer;

    // [cipherBufferSize]
    size_t dataSize = 246;//[data lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    const uint8_t* textData = [[data dataUsingEncoding:NSUTF8StringEncoding] bytes];

    SecKeyRef publicKey = [Encryption copyPublicKeyForTag:tag];

    NSAssert(publicKey, @"The public key being referenced by tag must have been stored in the keychain before attempting to encrypt data using it!");

    //  Allocate a buffer

    cipherBufferSize = SecKeyGetBlockSize(publicKey);
    // this value will not get modified, whereas cipherBufferSize may.
    const size_t fullCipherBufferSize = cipherBufferSize;
    cipherBuffer = malloc(cipherBufferSize);

    NSMutableData* accumulatedEncryptedData = [NSMutableData dataWithCapacity:0];

    //  Error handling

    for (int ii = 0; ii*fullCipherBufferSize < dataSize; ii++) {
        const uint8_t* dataToEncrypt = (textData+(ii*fullCipherBufferSize));
        const size_t subsize = (((ii+1)*fullCipherBufferSize) > dataSize) ? fullCipherBufferSize-(((ii+1)*fullCipherBufferSize) - dataSize) : fullCipherBufferSize;

        // Encrypt using the public key.
        status = SecKeyEncrypt(    publicKey,
                               kSecPaddingPKCS1,
                               dataToEncrypt,
                               subsize,
                               cipherBuffer,
                               &cipherBufferSize
                               );

        [accumulatedEncryptedData appendBytes:cipherBuffer length:cipherBufferSize];
    }

    if (publicKey) CFRelease(publicKey);

    free(cipherBuffer);

    return accumulatedEncryptedData;
}

1 个答案:

答案 0 :(得分:9)

来自文档:

  

plainTextLen
  plainText缓冲区中数据的字节长度。它必须小于或等于SecKeyGetBlockSize函数返回的值。 执行PKCS1填充时,可加密的最大数据长度比SecKeyGetBlockSize函数返回的值小11个字节(secKeyGetBlockSize() - 11)。

(强调我的)

您正在使用PKCS1填充。因此,如果块大小为256,则一次最多只能加密245个字节。