2012-10-16 2 views
4

파일에서 공개 키를 복구하려고합니다.파일에서 RSA를 복구하는 방법은 무엇입니까?

PublicKey readPubKeyFromFile(AssetFileDescriptor cle) throws IOException { 
    // read RSA public key 
    byte[] encodedKey = new byte[(int) cle.getDeclaredLength()]; 
    cle.createInputStream().read(encodedKey); 

    // create public key 
    X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey); 
    PublicKey pk = null; 
    try { 
     KeyFactory kf = KeyFactory.getInstance("RSA"); 
     pk = kf.generatePublic(publicKeySpec); 
    } catch(Exception e) { 
     Logger.getInstance().logError("KeyUtils", e.toString()); 
    } 
    return pk; 
} 

을 그리고 여기에 작동하지 않습니다 아이폰 OS 코드입니다 : 여기에 작동하는 자바 코드는

-(SecKeyRef)readPublicKeyFromFile:(NSString*)filename andExtension:(NSString*)extension { 

NSString* filePath = [[NSBundle mainBundle] pathForResource:filename ofType:extension]; 
NSData*  encodedKey = [NSData dataWithContentsOfFile:filePath]; 

CFDataRef myCertData = (CFDataRef)encodedKey; 

SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorSystemDefault, myCertData); 
CFArrayRef certs = CFArrayCreate(kCFAllocatorDefault, (const void **) &cert, 1, NULL); 
SecPolicyRef policy = SecPolicyCreateBasicX509(); 

SecTrustRef trust; 

OSStatus check = SecTrustCreateWithCertificates(certs, policy, &trust); 

if (check != noErr) 
{ 
    NSLog(@"Problem extracting public key from file: %@", filename); 
    return nil; 
} 

SecTrustResultType trustResult; 
SecTrustEvaluate(trust, &trustResult); 
SecKeyRef pub_key_leaf = SecTrustCopyPublicKey(trust); 

return pub_key_leaf; 
} 

내 아이폰 OS 코드를 잘못 무엇인지 어떤 생각?

+3

welcome to stackoverflow. 어떻게 작동하지 않니? –

+0

이렇게하면 nil을 반환합니다. SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorSystemDefault, myCertData); – ettibo

+0

모든 댓글, 나는 같은 지점에 스택입니다. – shebelaw

답변

1

코드를 테스트 한 결과 아무 문제가 없습니다. 이 문제는 공개 키를 얻으려고하는 인증서의 형식과 관련이있는 것으로 보입니다.

SecCertificateCreateWithData() 함수는 사용자가 제공하는 인증서가 DER 형식이라고 가정합니다. 찾은 대부분의 인증서는 유명한 .pem 형식과 같이 base64로 인코딩됩니다. 필자는 올바른 형식의 DER 인증서 (openssl을 사용하여 DER로 변환 된 인증서 양식 developer.apple.com)로 코드를 테스트했으며 공개 키가 올바르게 추출되었습니다.

는 .PEM 인증서가 단순히 DER 터미널에있는 OpenSSL을 사용하여 변환하려면 :

openssl x509 -in developer.apple.com.pem -outform der -out cert.der 

을 그 출력 인증서 파일 후 코드와 문제없이 작동합니다.

그러나 응용 프로그램 자체에서 인증서를 변환 할 수 있으며 x509 base64로 인코딩 된 인증서 (.pem 인 코드 인증서를 사용한다고 가정) 만 가져 와서 이진 형식으로 변환하면됩니다.

는 당신이 그것을 할 수있는 방법을 예를 들어 있습니다 :

이 코드는 인증서가 다음과 같은 표준으로 인코딩되어 있다고 가정합니다 : 진 DER이되는 코드는이 인증서를 변환하는

-----BEGIN CERTIFICATE----- 
< your base64 encoded certificate goes here > 
-----END CERTIFICATE----- 

:

:

-(NSData *)getBinaryCertificateFromPemEncodedFile:(NSString *)filename andExtension:(NSString *)extension 
{ 
    NSString* filePath = [[NSBundle mainBundle] pathForResource:filename ofType:extension]; 
    NSString *pemCert = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; 
    //The header and footer conforms to .pem specificatio 
    NSString *header = @"-----BEGIN CERTIFICATE-----"; 
    NSString *footer = @"-----END CERTIFICATE-----"; 

    NSString *base64Cert; 
    NSScanner *scanner = [NSScanner scannerWithString:pemCert]; 
    //First we ignore the header part 
    [scanner scanString:header intoString:nil]; 
    //Then we copy the base64 string excluding the footer 
    [scanner scanUpToString:footer intoString:&base64Cert]; 

    //The reason I'm using NSDataBase64DecodingIgnoreUnknownCharacters is to exclude possible line breaks in the encoding 
    NSData *binaryCertificate = [[NSData alloc] initWithBase64EncodedString:base64Cert options:NSDataBase64DecodingIgnoreUnknownCharacters]; 

    return binaryCertificate; 
} 

는 그런 다음 완벽하게 기능 코드의 작은 적응 트릭을 수행

NSData *data = [self getBinaryCertificateFromPemEncodedFile:@"developer" andExtension:@"pem"]; 
SecKeyRef key = [self readPublicKeyFromCertificate:data]; 
NSLog(@"%@", key); 

을 그리고 당신의 인증서가 "유효"인 경우 당신은 볼 수 :

-(SecKeyRef)readPublicKeyFromCertificate:(NSData *)binaryCertificate { 

    NSData *encodedKey = binaryCertificate; 

    CFDataRef myCertData = (CFDataRef)CFBridgingRetain(encodedKey); 

    SecCertificateRef cert = SecCertificateCreateWithData(kCFAllocatorSystemDefault, myCertData); 
    SecPolicyRef policy = SecPolicyCreateBasicX509(); 

    SecTrustRef trust; 
    //If you only have one certificate you don't need to put it inside an array 
    OSStatus check = SecTrustCreateWithCertificates(cert, policy, &trust); 

    if (check != noErr) 
    { 
     NSLog(@"Problem extracting public key from certificate"); 
     return nil; 
    } 

    SecTrustResultType trustResult; 
    SecTrustEvaluate(trust, &trustResult); 
    SecKeyRef pub_key_leaf = SecTrustCopyPublicKey(trust); 

    return pub_key_leaf; 
} 

그럼 그냥 전화를 테스트하기 위해

2014-09-15 21:52:13.275 cert[15813:60b] <SecKeyRef algorithm id: 1, 
key type: RSAPublicKey, version: 2, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, 
modulus: BE19E30F47F2D31F27D576CF007B3E615F986D14AFD0D52B825E01E90BA3E1CBB6F3A472E6AECDC28BC13D0B6E58FC497ACF61D80F274E4799602DA4F819E54ADDE2FBFA89FC4EB2172501DDED8DE0FBDDBC5550CC018C73E1FD8152C905DE850862B8D57596025DE1908D8337E95637AF0F52C4A11DA178FF737DCE09471BC0A49DAD7DB39F1BA1B693D3A12F9CA50EF388B50292C73076BF1EEE412A5CFA940E99D4CF07F17FAC87F0D0E2FC8FA3ACDDEEFCCE8AFEC407B94536FCB1E4ACF34773728D189F85EAE4347E0BF868D25C7CE89F8A29B4E6865C68F4F915DFA540549EE9333007145D367FE2852622AAD776F3E5D505A02E5155CC8646A01C1031, 
addr: 0x9a48200> 

나는 developer.apple.com에서 인증서를 사용했습니다 로그에서 공개 키를 확인하고 비교할 수 있습니다.

관련 문제