使用Java Security生成的XCode导入公钥文件

时间:2013-08-07 14:23:08

标签: java xcode public-key-encryption

我有一个java生成器公钥:

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();

另一方面,我有xcode,它使用这个publickey.der来加密数据:

    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;
}

但是我说无法从public_key.der读取证书。

好吧,如果我使用openssl public_key就行了。为什么?哪个是openssl keypairgenerator之间的区别。

感谢。

1 个答案:

答案 0 :(得分:0)

您的Java代码不会创建真正的证书。您生成了一个公钥。如何从java生成的公钥获取PublicKeyRef在this post中描述。你可以从文件中读取xcode中的这个公钥,但是你需要做一些额外的事情。

- (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;

}

然后使用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;

}

您可以生成公钥

- (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.    
}