【发布时间】:2015-05-22 08:41:16
【问题描述】:
我正在尝试使用我将从 pem 证书中获得的私钥签署一个特定的字符串。此证书使用密码短语加密。证书格式(.pem 文件)是这样的:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,A60C80692F0FEB16
Fq/awhS....
+..
+..
+..
+..
+....detSug=
-----END RSA PRIVATE KEY-----
我为从此证书获取公钥和私钥而编写的代码是:
import java.io.FileReader;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import org.bouncycastle.asn1.ASN1Generator;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.openssl.PEMDecryptorProvider;
import org.bouncycastle.openssl.PEMEncryptedKeyPair;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import sun.misc.BASE64Encoder;
class MainClass{
public static void main(String args[]){
try{
PrivateKey pk = readPrivateKey("C:/Input/CERT.pem","passphrase");
PublicKey pubk = readPublicKey("C:/Input/CERT.pem","passphrase");
byte[] data = "ABCEFG20150520163306".getBytes("UTF8");
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(pk);
sig.update(data);
byte[] signatureBytes = sig.sign();
System.out.println("Singature:" + new BASE64Encoder().encode(signatureBytes));
sig.initVerify(pubk);
sig.update(data);
System.out.println(sig.verify(signatureBytes));
}catch(Exception e){
e.printStackTrace();
}
}
private static PrivateKey readPrivateKey(String privateKeyPath, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKeyPath);
PEMParser keyReader = new PEMParser(fileReader);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PEMDecryptorProvider decryptionProv = new JcePEMDecryptorProviderBuilder().build(keyPassword.toCharArray());
System.out.println(keyReader.getClass());
Object keyPair = keyReader.readObject();
PrivateKeyInfo keyInfo;
System.out.println(keyPair.getClass());
if (keyPair instanceof PrivateKeyInfo) {
System.out.println("Correct instance found");
PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProv);
keyInfo = decryptedKeyPair.getPrivateKeyInfo();
} else {
keyInfo = ((PEMKeyPair) keyPair).getPrivateKeyInfo();
}
keyReader.close();
return converter.getPrivateKey(keyInfo);
}
private static PublicKey readPublicKey(String privateKeyPath, String keyPassword) throws IOException {
FileReader fileReader = new FileReader(privateKeyPath);
PEMParser keyReader = new PEMParser(fileReader);
JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
PEMDecryptorProvider decryptionProv = new JcePEMDecryptorProviderBuilder().build(keyPassword.toCharArray());
Object keyPair = keyReader.readObject();
SubjectPublicKeyInfo keyInfo;
if (keyPair instanceof PEMEncryptedKeyPair) {
PEMKeyPair decryptedKeyPair = ((PEMEncryptedKeyPair) keyPair).decryptKeyPair(decryptionProv);
keyInfo = decryptedKeyPair.getPublicKeyInfo();
} else {
keyInfo = ((PEMKeyPair) keyPair).getPublicKeyInfo();
}
keyReader.close();
return converter.getPublicKey(keyInfo);
}
}
这段代码工作正常,但现在我必须为看起来像这样的 ASN1 证书做同样的事情
Bag Attributes
localKeyID: 01 00 00 00
friendlyName: le-d5391255-2e94-48fe-8327-caca5d9aa498<Microsoft CSP Name: Microsoft Enhanced Cryptographic Provider v1.0
Key Attributes
X509v3 Key Usage: 10
-----BEGIN PRIVATE KEY-----
MIIEvwIBA....
+..
+..
+..
+..
+....N5kNrDV0Yg==
-----END PRIVATE KEY-----
Bag Attributes
localKeyID: 00 01 00 00
1.3.6.1.4.1.322.17.3.92: 00 08 00 00
1.3.6.1.4.1.311.17.3.20: 15 0D 78 6A D0 18 CB A2 D1 7F D1 C2 B2 7A E0 53 70 D7 ED F9
1.3.6.1.4.1.313.17.3.79: 46 00 61 00 9E 00 65 00 73 00 73 00 61 00 2D 00 50 00 43 00 00 00
subject=/C=SG/O=Netrust Certificate Authority 1/OU=Netrust CA1 (Server)/OU=ABC-XYZ Private Limited/CN=QICERT
issuer=/C=SG/O=Netrust Certificate Authority 1/OU=Netrust CA
-----BEGIN CERTIFICATE-----
MIIE5DCCA8yg....
+..
+..
+..
+..
+....Y7LF
Byuyq1Pe4QY=
-----END CERTIFICATE-----
Bag Attributes
1.3.6.1.4.1.311.17.3.92: 00 08 00 00
1.3.1.1.4.1.221.17.3.20: 1D 44 89 B2 45 26 7F 3F 6B 92 C5 3A 7B 72 63 CA D2 70 2A DD
subject=/C=SG/O=Netrust Certificate Authority 1/OU=Netrust CA1
issuer=/C=SG/O=Netrust Certificate Authority 1/OU=Netrust CA1
-----BEGIN CERTIFICATE-----
MIIESTCCAzGgAwI....
+..
+..
+..
+..
+....Y7LF
iY44mB2Sev4/02GkW7
-----END CERTIFICATE-----
当我为这个新证书运行此代码时,我收到以下错误:
java.lang.ClassCastException: org.bouncycastle.asn1.pkcs.PrivateKeyInfo cannot be cast to org.bouncycastle.openssl.PEMEncryptedKeyPair
at MainClass.readPrivateKey(MainClass.java:92)
at MainClass.main(MainClass.java:47)
基于此错误消息,我正在尝试更改我的代码以获取 ASN1 类型的私钥-公钥对,但我无法这样做。
谢谢!
【问题讨论】:
-
签名不需要公钥。
-
是的,您是对的,仅使用私钥完成签名,但可以使用公钥完成验证!
标签: java security ssl encryption asn.1