Converting NSData to SecKeyRef

前端 未结 2 1808
情话喂你
情话喂你 2020-12-15 12:08

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 arr

相关标签:
2条回答
  • 2020-12-15 12:52

    Hope It will work....

    -(NSData*)convertIOSKeyToASNFormat:(NSData*)iosKey{
    
        static const unsigned char _encodedRSAEncryptionOID[15] = {
            /* Sequence of length 0xd made up of OID followed by NULL */
            0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
            0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00
        };
    
        // OK - that gives us the "BITSTRING component of a full DER
        // encoded RSA public key - we now need to build the rest
    
        unsigned char builder[15];
        NSMutableData * encKey = [[[NSMutableData alloc] init] autorelease];
        int bitstringEncLength;
    
        // When we get to the bitstring - how will we encode it?
        if  ([iosKey length ] + 1  < 128 )
            bitstringEncLength = 1 ;
        else
            bitstringEncLength = (([iosKey length ] +1 ) / 256 ) + 2 ;
    
        // Overall we have a sequence of a certain length
        builder[0] = 0x30;    // ASN.1 encoding representing a SEQUENCE
    
        // Build up overall size made up of -
        size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength +
        [iosKey length];
    
        size_t j = [self encodeLen:&builder[1] length:i];
        [encKey appendBytes:builder length:j +1];
    
        // First part of the sequence is the OID
        [encKey appendBytes:_encodedRSAEncryptionOID
                     length:sizeof(_encodedRSAEncryptionOID)];
    
        // Now add the bitstring
        builder[0] = 0x03;
        j = [self encodeLen:&builder[1] length:[iosKey length] + 1];
    
        builder[j+1] = 0x00;
        [encKey appendBytes:builder length:j + 2];
    
        // Now the actual key
        [encKey appendData:iosKey];
        return encKey;
    }
    
    0 讨论(0)
  • 2020-12-15 13:01

    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]);
    
    }
    
    0 讨论(0)
提交回复
热议问题