如何从文件中恢复 RSA?
Posted
技术标签:
【中文标题】如何从文件中恢复 RSA?【英文标题】:How to recover RSA from file? 【发布时间】:2012-10-06 12:44:05 【问题描述】:我想从文件中恢复公钥。这是有效的 Java 代码:
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;
这是不起作用的 ios 代码:
-(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;
知道我的 iOS 代码出了什么问题吗?
【问题讨论】:
欢迎使用 ***。怎么不行? 返回 nil:SecCertificateRef cert = SecCertificateCreateWithData (kCFAllocatorSystemDefault, myCertData); 任何评论,我都在同一个地方。 你好,实际上我必须使用openssl并自己解析文件。似乎密钥是用 Java 生成的,格式不标准:s 【参考方案1】:我已经测试了您的代码,没有任何问题。该问题似乎与您尝试获取公钥的证书格式有关。
SecCertificateCreateWithData() 函数假定您提供的证书是 DER 格式。您发现的大多数证书都以 base64 编码,如著名的 .pem 格式。我已经使用正确格式的 DER 证书(使用 openssl 将证书表单 developer.apple.com 转换为 DER)测试了您的代码,并且正确提取了公钥。
要将 .pem 证书转换为 DER,只需在终端中使用 openssl:
openssl x509 -in developer.apple.com.pem -outform der -out cert.der
之后,输出证书文件应该可以正常使用您的代码了。
但你可以在应用程序本身上转换证书,你只需要抓取 de x509 base64 编码的证书(假设你使用的是 .pem 编码的证书)并将其转换为二进制。
有一个例子可以做到:
此代码将假定证书按以下标准编码:
-----BEGIN CERTIFICATE-----
< your base64 encoded certificate goes here >
-----END CERTIFICATE-----
将此证书转换为二进制 DER 的代码是:
-(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;
然后在您完美的功能代码中进行一个小的修改就可以了:
-(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;
那就直接调用吧:
NSData *data = [self getBinaryCertificateFromPemEncodedFile:@"developer" andExtension:@"pem"];
SecKeyRef key = [self readPublicKeyFromCertificate:data];
NSLog(@"%@", key);
如果您的证书“有效”,您应该会看到:
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 的证书,你可以查看日志中的公钥并进行比较。
【讨论】:
以上是关于如何从文件中恢复 RSA?的主要内容,如果未能解决你的问题,请参考以下文章