简体   繁体   中英

XCode import public key file generated with Java Security

I have a java generator public key as this:

final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
PublicKey pubkey = key.getPublic();
byte[] key = pubkey .getEncoded();
FileOutputStream keyfos = new FileOutputStream("publicKey.der");
keyfos.write(key);
keyfos.close();

And on another hand, i have xcode,that use this publickey.der to encrypt data:

    NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key"
ofType:@"der"];
if (publicKeyPath == nil) {
NSLog(@"Can not find public_key.der");
return nil;
}
NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
if (publicKeyFileContent == nil) {
NSLog(@"Can not read from public_key.der");
return nil;
 }
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);
if (certificate == nil) {
NSLog(@"Can not read certificate from public_key.der");
return nil;
}
policy = SecPolicyCreateBasicX509();
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);
if (returnCode != 0) {
NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);
return nil;

    }
SecTrustResultType trustResultType;
returnCode = SecTrustEvaluate(trust, &trustResultType);
if (returnCode != 0) {
 NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);
return nil;
}
publicKey = SecTrustCopyPublicKey(trust);
if (publicKey == nil) {
 NSLog(@"SecTrustCopyPublicKey fail");
return nil;
}

but said me that Can not read certificate from public_key.der.

Well, if i use a openssl public_key it works. Why? Which is the difference openssl keypairgenerator between.

Thanks.

Your Java code does not create a real certificate. You generated a public key. How to get PublicKeyRef from java generated public key is described in this post . You can read this public key in xcode from a file, but then you need to do some additional stuff.

- (NSData *) extractPublicKeyFromRawFormattedKey: (NSData *) rawFormattedKey {
/* Now strip the uncessary ASN encoding guff at the start */
unsigned char * bytes = (unsigned char *)[rawFormattedKey bytes];
size_t bytesLen = [rawFormattedKey length];

/* Strip the initial stuff */
size_t i = 0;
if (bytes[i++] != 0x30)
    return FALSE;

/* Skip size bytes */
if (bytes[i] > 0x80)
    i += bytes[i] - 0x80 + 1;
else
    i++;

if (i >= bytesLen)
    return FALSE;

if (bytes[i] != 0x30)
    return FALSE;

/* Skip OID */
i += 15;

if (i >= bytesLen - 2)
    return FALSE;

if (bytes[i++] != 0x03)
    return FALSE;

/* Skip length and null */
if (bytes[i] > 0x80)
    i += bytes[i] - 0x80 + 1;
else
    i++;

if (i >= bytesLen)
    return FALSE;

if (bytes[i++] != 0x00)
    return FALSE;

if (i >= bytesLen)
    return FALSE;

/* Here we go! */
NSData * extractedKey = [NSData dataWithBytes:&bytes[i] length:bytesLen - i];

return extractedKey;

}

Then using method from apple example

- (SecKeyRef)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKey {
OSStatus sanityCheck = noErr;
SecKeyRef peerKeyRef = NULL;
CFTypeRef persistPeer = NULL;

LOGGING_FACILITY( peerName != nil, @"Peer name parameter is nil." );
LOGGING_FACILITY( publicKey != nil, @"Public key parameter is nil." );

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:publicKey forKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&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.

LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecDuplicateItem, @"Problem adding the peer public key to the keychain, OSStatus == %d.", sanityCheck );

if (persistPeer) {
    peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer];
} else {
    [peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
    [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
    // Let's retry a different way.
    sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
}

LOGGING_FACILITY1( sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %d.", sanityCheck );

[peerTag release];
[peerPublicKeyAttr release];
if (persistPeer) CFRelease(persistPeer);
return peerKeyRef;

}

you can generate a public key

- (void)generatePublicKeyByFile {
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key"
ofType:@"der"];
NSData *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
NSData *publicKey = [self extractPublicKeyFromRawFormattedKey:publicKeyFileContent];
[[SecKeyWrapper sharedWrapper] removePeerPublicKey:@"peerName"]; //remove public key if it is already added.
SecKeyRef publicKeyRef = [[SecKeyWrapper sharedWrapper]addPeerPublicKey:@"peerName" keyBits:publicKey]; //our goal.    
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM