【发布时间】:2020-04-24 19:02:01
【问题描述】:
我使用Java KeyStore Explorer 创建了一个密钥对 EC NIST P-256:
[
PRIVATE 密钥的 ASN.1 格式如下所示:
SEQUENCE
{
INTEGER=0
SEQUENCE
{
OBJECT IDENTIFIER=EcPublicKey (1.2.840.10045.2.1)
OBJECT IDENTIFIER=Prime256v1 (1.2.840.10045.3.1.7)
}
OCTET STRING, encapsulates:
SEQUENCE
{
INTEGER=1
OCTET STRING=
A3 6E C5 71 D3 15 F1 87 ÃnÅqÓ.õ.
E9 BF AF 78 74 74 67 BC é¿ xttg¼
4D A0 69 BF 53 3A C2 E0 M i¿S:Âà
D8 F6 F5 BC 2E C1 B4 CC Øöõ¼..´Ì
TAGGED [0]:
OBJECT IDENTIFIER=Prime256v1 (1.2.840.10045.3.1.7)
TAGGED [1]:
BIT STRING=
E6 A9 E2 62 AB 3C 9E 43 ..^Ñ..)X
E6 A9 E2 62 AB 3C 9E 43 #óþ[æEYî
E6 A9 E2 62 AB 3C 9E 43 .h®Î..Ë5
E6 A9 E2 62 AB 3C 9E 43 #óþ[æEYî
E6 A9 E2 62 AB 3C 9E 43 &.^5.ù¥.
E6 A9 E2 62 AB 3C 9E 43 #óþ[æEYî
E6 A9 E2 62 AB 3C 9E 43 #óþ[æEYî
E6 A9 E2 62 AB 3C 9E 43 .Ëkut.èö
93 .
}
}
然后我尝试通过代码实现相同的目标:
private static final String KEY_BEGIN_PRIVATE = "-----BEGIN PRIVATE KEY-----\n";
private static final String KEY_END_PRIVATE = "-----END PRIVATE KEY-----\n";
private static void CreateCertificate(BigInteger serialNumber) throws Exception {
//Create key
KeyPairGenerator keypairGen = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec ecgenspec = new ECGenParameterSpec(curve); //curve = "NIST P-256"
keypairGen.initialize(ecgenspec);
KeyPair keypair = keypairGen.generateKeyPair()
X500Name subject = CreateSubject();
X509v3CertificateBuilder certificate = CreateCertificateBuilder(subject,
keypair.getPublic(), serialNumber);
ContentSigner signer = new JcaContentSignerBuilder("SHA256withECDSA")
.build(keypair.getPrivate());
X509CertificateHolder holder = certificate.build(signer);
JcaX509CertificateConverter converter = new JcaX509CertificateConverter();
converter.setProvider(new BouncyCastleProvider());
X509Certificate x509 = converter.getCertificate(holder);
// Encode to pem
org.apache.commons.codec.binary.Base64 encoder = new
org.apache.commons.codec.binary.Base64(64);
byte[] derKey = key.getEncoded();
String pemKey = KEY_BEGIN_PRIVATE + encoder.encodeAsString(derKey) + KEY_END_PRIVATE;
//Write to disk
writer = null;
File file = new File("somepath");
file.createNewFile();
writer = new BufferedWriter(new FileWriter(file));
writer.write(pemKey);
writer.close();
}
密钥创建工作正常,没有错误,但 ASN.1 中的密钥看起来不同,尽管算法是相同的。缺少 TAGGED [1] 部分。
SEQUENCE
{
INTEGER=0
SEQUENCE
{
OBJECT IDENTIFIER=EcPublicKey (1.2.840.10045.2.1)
OBJECT IDENTIFIER=Prime256v1 (1.2.840.10045.3.1.7)
}
OCTET STRING, encapsulates:
SEQUENCE
{
INTEGER=1
OCTET STRING=
66 28 18 9F 7C 34 7A 5B f(..|4z[
23 F3 FE 5B E6 45 59 EE #óþ[æEYî
E6 A9 E2 62 AB 3C 9E 43 æ©âb«<.C
7B CC 8C 13 D1 26 3B 87 {Ì..Ñ&;.
TAGGED [0]:
OBJECT IDENTIFIER=Prime256v1 (1.2.840.10045.3.1.7)
}
}
我有一个读取私钥和一些证书的应用程序。
使用通过 java keystore explorer 工具生成的私钥,一切正常,但使用代码生成的密钥和证书,应用程序在读取私钥时失败:
java.lang.IllegalArgumentException: Illegal base64 character d
在我看来,这与我如何创建密钥和证书有关,但是告诉我我的基本编码错误的异常让我想知道,因为在导入时使用密钥库资源管理器和通过 openssl 可以很好地读取密钥命令行。
我的问题是:
- 我在代码中是否有一些愚蠢的错误或错误?
- java 密钥库资源管理器与我有什么不同?
我尝试了不同的方法来使用不同的库进行 Base64 编码,但这没有任何区别。
附加:我无权访问读取密钥和证书的应用程序的源代码,因此我无法检查实现。但由于这个事实,其他键有效,我认为错误在我这边。密钥不会用于任何生产或测试场景,所以在这里发布它们是安全的,我也修改了值,但这对你没有任何影响。
【问题讨论】:
-
错误是应用程序需要 base64 数据但没有得到它。由于您没有源代码并且“d”是有效的 base64 字符,我只能猜测错误是指 CR 字符 0x0d。将这些从您的 base64 数据中取出。也许摆脱所有的空白。
-
可能在
java.util中使用Java Base64 编码器。您删除一个依赖项,默认情况下它不会生成空格。
标签: java cryptography