将NSData转换为SecKeyRef [英] Converting NSData to SecKeyRef
问题描述
+(NSString *)encryptRSA(NSString *)plainTextString withKey:(SecKeyRef)publicKey {
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t * cipherBuffer = malloc(cipherBufferSize);
uint8_t * nonce =(uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingOAEP,
nonce,
strlen((char *)nonce),
& cipherBuffer [0],
& cipherBufferSize);
NSData * encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
如你所见需要SecKeyRef对象类型来完成我的加密。但是我的RSA公钥是NSData变量。那么如何将NSData转换为SecKeyRef对象类型。感谢提前。
使用此功能保存您的公钥。传递您的RAS公钥和任何名称为peername。
- (void)addPeerPublicKey:(NSString *)peerName keyBits :( NSData *)publicKeyData {
OSStatus sanityCheck = noErr;
CFTypeRef persistPeer = NULL;
[self removePeerPublicKey:peerName];
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:publicKeyData forKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];
sanityCheck = SecItemAdd((CFDictionaryRef)peerPublicKeyAttr,(CFTypeRef *)& persistPeer);
if(sanityCheck == errSecDuplicateItem){
TRC_DBG(@将对等公钥添加到钥匙串,OSStatus ==%ld,sanityCheck);
}
TRC_DBG(@SecItemAdd OSStATUS =%ld,sanityCheck);
// TRC_DBG(@PersistPeer导入到钥匙串%@中的私钥数据,persistPeer);
persistPeer = NULL;
[peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
sanityCheck = SecItemCopyMatching((CFDictionaryRef)peerPublicKeyAttr,(CFTypeRef *)& persistPeer);
TRC_DBG(@SecItemCopying OSStATUS =%ld,sanityCheck);
// TRC_DBG(@SecItem复制匹配返回此公钥数据%@,persistPeer);
//持久引用的好处是可以将它们的值写入磁盘,然后
//然后再使用它们。我不这样做,但是对于其他情况来说肯定是有意义的,你不想不断地建立字典的属性来获得引用。
//
//另请看看SecKeyWrapper的方法(CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
//& (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef。
[peerTag release];
[peerPublicKeyAttr release];
if(persistPeer)CFRelease(persistPeer);
}
这是检索公钥参考的函数。通过相同的名称,一个用于保存。
- (SecKeyRef)getPublicKeyReference:(NSString *)peerName {
OSStatus sanityCheck = noErr;
SecKeyRef pubKeyRefData = NULL;
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
sanityCheck = SecItemCopyMatching((CFDictionaryRef)peerPublicKeyAttr,(CFTypeRef *)& pubKeyRefData);
[peerTag release];
[peerPublicKeyAttr release];
TRC_DBG(@SecItemCopying OSStATUS =%ld,sanityCheck);
if(pubKeyRefData){
TRC_DBG(@SecItem copy matching returned this publickeyref%@,pubKeyRefData);
return pubKeyRefData;
} else {
TRC_DBG(@pubKeyRef is NULL);
return nil;
}
}
将您的公钥数据传递给此函数,然后再添加到AddPeerPublicKey
- (NSData *)stripPublicKeyHeader:(NSData *)d_key
{
//跳过ASN.1 public key header
if(d_key == nil)return(nil);
unsigned int len = [d_key length];
if(!len)return(nil);
unsigned char * c_key =(unsigned char *)[d_key bytes];
unsigned int idx = 0;
if(c_key [idx ++]!= 0x30)return(nil);
if(c_key [idx]> 0x80)idx + = c_key [idx] - 0x80 + 1;
else idx ++;
// PKCS#1 rsaEncryption szOID_RSA_RSA
static unsigned char seqiod [] =
{0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d ,0x01,0x01,
0x01,0x05,0x00};
if(memcmp(& c_key [idx],seqiod,15))return(nil);
idx + = 15;
if(c_key [idx ++]!= 0x03)return(nil);
if(c_key [idx]> 0x80)idx + = c_key [idx] - 0x80 + 1;
else idx ++;
if(c_key [idx ++]!='\0')return(nil);
//现在从这个缓冲区创建一个新的NSData
return([NSData dataWithBytes:& c_key [idx] length:len-idx]);
}
i have a public key which i gathered from a remote server and i want to perform RSA encryption with that public key. But the problem is i get the public key data as byte array in buffer. I can convert it to NSData but i can not convert to SecKeyRef so i can keep going with encryption. My encryption code is like:
+(NSString *)encryptRSA:(NSString *)plainTextString withKey:(SecKeyRef)publicKey {
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize);
uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingOAEP,
nonce,
strlen( (char*)nonce ),
&cipherBuffer[0],
&cipherBufferSize);
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
As you can see i need SecKeyRef object type to complete my encryption. But my RSA public key is in NSData variable. So how can i convert NSData to SecKeyRef object type. Thanks in advance.
Use this function to save your public key. Pass your RAS public key and any name for peername.
- (void)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKeyData {
OSStatus sanityCheck = noErr;
CFTypeRef persistPeer = NULL;
[self removePeerPublicKey:peerName];
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:publicKeyData forKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];
sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);
if(sanityCheck == errSecDuplicateItem){
TRC_DBG(@"Problem adding the peer public key to the keychain, OSStatus == %ld.", sanityCheck );
}
TRC_DBG(@"SecItemAdd OSStATUS = %ld", sanityCheck);
// TRC_DBG(@"PersistPeer privatekey data after import into keychain %@", persistPeer);
persistPeer = NULL;
[peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&persistPeer);
TRC_DBG(@"SecItemCopying OSStATUS = %ld", sanityCheck);
// TRC_DBG(@"SecItem copy matching returned this public key data %@", persistPeer);
// The nice thing about persistent references is that you can write their value out to disk and
// then use them later. I don't do that here but it certainly can make sense for other situations
// where you don't want to have to keep building up dictionaries of attributes to get a reference.
//
// Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
// & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.
[peerTag release];
[peerPublicKeyAttr release];
if (persistPeer) CFRelease(persistPeer);
}
This is the function to retrieve the public key ref. Pass the same name which one is used for save.
-(SecKeyRef)getPublicKeyReference:(NSString*)peerName{
OSStatus sanityCheck = noErr;
SecKeyRef pubKeyRefData = NULL;
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey: (id)kSecReturnRef];
sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&pubKeyRefData);
[peerTag release];
[peerPublicKeyAttr release];
TRC_DBG(@"SecItemCopying OSStATUS = %ld", sanityCheck);
if(pubKeyRefData){
TRC_DBG(@"SecItem copy matching returned this publickeyref %@", pubKeyRefData);
return pubKeyRefData;
}else{
TRC_DBG(@"pubKeyRef is NULL");
return nil;
}
}
Pass your public key data to this function before addPeerPublicKey
- (NSData *)stripPublicKeyHeader:(NSData *)d_key
{
// Skip ASN.1 public key header
if (d_key == nil) return(nil);
unsigned int len = [d_key length];
if (!len) return(nil);
unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = 0;
if (c_key[idx++] != 0x30) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
// PKCS #1 rsaEncryption szOID_RSA_RSA
static unsigned char seqiod[] =
{ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00 };
if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
idx += 15;
if (c_key[idx++] != 0x03) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
if (c_key[idx++] != '\0') return(nil);
// Now make a new NSData from this buffer
return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}
这篇关于将NSData转换为SecKeyRef的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!