我正在尝试实施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 plainBuffer
到NSData
或简单地NSString
,以便我将字符串恢复。我的加密和密钥生成代码请参阅此reference。
提前致谢..
答案 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];