在RSA解密中将uint8_t转换为NSString

时间:2013-01-14 19:01:06

标签: iphone ios objective-c ios5

我正在尝试实施RSA算法,我遵循了苹果reference。 但我有问题将uint8_t转换为NSData到NSString。

到目前为止,我已经完成了这项工作。这些函数在reference

中定义
-(void)test{
    [self generateKeyPairPlease];
    NSData *data = [self encryptWithPublicKey]; //All goes well until here
    [self decryptWithPrivateKey:data]; 

}

对于加密,我做了..

- (NSData *)encryptWithPublicKey
{
    OSStatus status = noErr;

    size_t cipherBufferSize;
    uint8_t *cipherBuffer;                     // 1

// [cipherBufferSize]
    const uint8_t dataToEncrypt[] = "the quick brown fox jumps "
                            "over the lazy dog\0"; // 2
    size_t dataLength = sizeof(dataToEncrypt)/sizeof(dataToEncrypt[0]);

    SecKeyRef publicKey = NULL;                                 // 3

    NSData * publicTag = [NSData dataWithBytes:publicKeyIdentifier
             length:strlen((const char *)publicKeyIdentifier)]; // 4

    NSMutableDictionary *queryPublicKey =
                            [[NSMutableDictionary alloc] init]; // 5

    [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
    [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
    [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
                                                                // 6

    status = SecItemCopyMatching
    ((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKey); // 7

//  Allocate a buffer

    cipherBufferSize = SecKeyGetBlockSize(publicKey);
    cipherBuffer = malloc(cipherBufferSize);

//  Error handling

    if (cipherBufferSize < sizeof(dataToEncrypt)) {
        // Ordinarily, you would split the data up into blocks
        // equal to cipherBufferSize, with the last block being
        // shorter. For simplicity, this example assumes that
        // the data is short enough to fit.
        printf("Could not decrypt.  Packet too large.\n");
        return NULL;
    }

    // Encrypt using the public.
    status = SecKeyEncrypt(    publicKey,
                                kSecPaddingPKCS1,
                                dataToEncrypt,
                                (size_t) dataLength,
                                cipherBuffer,
                                &cipherBufferSize
                                );                              // 8

//  Error handling
//  Store or transmit the encrypted text

    if (publicKey) CFRelease(publicKey);

    NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:dataLength];

    free(cipherBuffer);

    return encryptedData;
}

但在decryptWithPrivateKey我无法将uint8_t *plainBuffer(解密结果)转换为NSString。首先,我尝试使用{{打印时将其转换为NSData 1}}它正确显示字节但后来NSLog没有转换为字符串。

NSData

我想知道如何将解密结果- (void)decryptWithPrivateKey: (NSData *)dataToDecrypt { OSStatus status = noErr; size_t cipherBufferSize = [dataToDecrypt length]; uint8_t *cipherBuffer = (uint8_t *)[dataToDecrypt bytes]; size_t plainBufferSize; uint8_t *plainBuffer; SecKeyRef privateKey = NULL; NSData * privateTag = [NSData dataWithBytes:privateKeyIdentifier length:strlen((const char *)privateKeyIdentifier)]; NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init]; // Set the private key query dictionary. [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass]; [queryPrivateKey setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag]; [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef]; // 1 status = SecItemCopyMatching ((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKey); // 2 // Allocate the buffer plainBufferSize = SecKeyGetBlockSize(privateKey); plainBuffer = malloc(plainBufferSize); if (plainBufferSize < cipherBufferSize) { // Ordinarily, you would split the data up into blocks // equal to plainBufferSize, with the last block being // shorter. For simplicity, this example assumes that // the data is short enough to fit. printf("Could not decrypt. Packet too large.\n"); return; } // Error handling status = SecKeyDecrypt( privateKey, kSecPaddingPKCS1, cipherBuffer, cipherBufferSize, plainBuffer, &plainBufferSize ); // 3 //******************************************************************************* // Not able to convert uint8_t *plainBuffer to string // I also tried to convert it into NSData and then try to convert it into NSString but can't //What Should i do here to get string back if(privateKey) CFRelease(privateKey); } @end 转换为uint8_t plainBufferNSData或简单地NSString,以便我将字符串恢复。我的加密和密钥生成代码请参阅此reference

提前致谢..

3 个答案:

答案 0 :(得分:6)

我知道这个问题已经过时并标记为已解决,但我遇到了类似的问题。 我发现的是,行中的苹果文档加密方法似乎有错误

NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:dataLength];

datalength是错误的变量。我用cipherbuffersize替换它

NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];

现在每件事都适合我。我希望它对我以外的其他人有用。

答案 1 :(得分:1)

最可能的问题是你正在调用+[stringWithCharacters:length:],它需要Unicode字符(更确切地说,UTF-16代码点),但你可能有UTF-8或其他8位编码。

您必须知道您拥有哪种编码,因此您可以拨打+[stringWithCString:encoding:](或者,如果它是UTF-8,简称+[stringWithUTF8String:])。

请注意,与stringWithCharacters不同,这些方法不需要长度,并且期望您的数据以空值终止。因此,除非您确定数据始终具有终止符,否则您应该显式检查它,或者分配字符串然后调用-[initWithBytes:length:encoding:]

如果您在加密之前不知道明文是什么字符集,您需要找出答案。作为一个人,你经常可以通过观察它来判断,特别是如果它主要是ASCII。使用缓冲区创建NSData并记录该内容并查看十六进制。如果它是UTF-16,则ASCII字符将与空值交替,因此'Hello'将为48 00 65 00 6C 00 6C 00 6F 00。但是计算机不会做得很好。 (+[stringWithContentsOfFile:usedEncoding:error:]通常正确的原因是它查看扩展属性com.apple.TextEncoding,大多数Cocoa应用程序在保存文件时会写入。{/ p>

答案 2 :(得分:0)

我设法按照code来解决我的问题。这是相同的代码,但字符串的编码是不同的。在encryptWithPublicKey函数中我使用了

uint8_t *dataToEncrypt= (uint8_t *)[@"the quick brown fox jumps over the lazy dog" UTF8String];

而不是

const uint8_t dataToEncrypt[] = "the quick brown fox jumps " "over the lazy dog\0";

并且在decryptWithPrivateKey我用它来解码

 NSData *decryptedData = [NSData dataWithBytes:plainBuffer length:plainBufferSize];
 NSString *decryptedString = [[[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding] autorelease];