我正在生成一个 key 对,用于使用椭圆曲线算法进行签名。生成私钥后,我将其存储在 KeyStore 中并将其写入文件。当我调用 Key.getAlgorithm 时,它返回“ECDSA”。但从文件中重新加载 KeyStore 后,Key.getAlgorithm 返回“EC”。我想知道这是从哪里来的以及为什么保存后会得到不同的结果。
这是我的代码(注意,要运行此代码,您需要在 jre 中安装 JCE 无限强度策略文件):
public static void main(String [] args) throws Exception
{
String PROVIDER = "BC";
String KEY_ALGORITHM = "ECDSA";
String SIGNATURE_ALGORITHM = "SHA1WITHECDSA";
String ALIAS = "TestAlias";
char [] PASSWORD = "password".toCharArray();
String KEYSTORE = "c:/test/bugs/keystore.p12";
Security.addProvider(new BouncyCastleProvider());
// Generate the key
Calendar calNow = Calendar.getInstance();
Calendar calLater = Calendar.getInstance();
calLater.set(Calendar.YEAR, calLater.get(Calendar.YEAR) + 25);
Date startDate = new Date(calNow.getTimeInMillis());
Date expiryDate = new Date(calLater.getTimeInMillis());
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp192r1");
KeyPairGenerator g = KeyPairGenerator.getInstance(KEY_ALGORITHM, PROVIDER);
g.initialize(ecSpec, new SecureRandom());
KeyPair keyPair = g.generateKeyPair();
X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
X500Principal dnName = new X500Principal("CN=Test");
certGen.setSerialNumber(new BigInteger(8, new SecureRandom()));
certGen.setIssuerDN(dnName);
certGen.setNotBefore(startDate);
certGen.setNotAfter(expiryDate);
certGen.setSubjectDN(dnName); // note: same as issuer
certGen.setPublicKey(keyPair.getPublic());
certGen.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
X509Certificate cert = certGen.generate(keyPair.getPrivate(), PROVIDER);
// Save the keystore
KeyStore exportStore = KeyStore.getInstance("PKCS12", PROVIDER);
exportStore.load(null, null);
exportStore.setKeyEntry(ALIAS, keyPair.getPrivate(), PASSWORD, new Certificate[] { cert });
FileOutputStream out = new FileOutputStream(KEYSTORE);
exportStore.store(out, PASSWORD);
out.flush();
out.close();
// print the info from the keystore
System.out.println(exportStore.getKey(ALIAS, PASSWORD).getAlgorithm());
// Reload the keystore
FileInputStream in = new FileInputStream(KEYSTORE);
exportStore.load(in, PASSWORD);
in.close();
// print the info from the reloaded keystore
System.out.println(exportStore.getKey(ALIAS, PASSWORD).getAlgorithm());
}
基于this example from Bouncy Castle ,生成 key 对时使用“ECDSA”似乎是正确的。
最佳答案
Oracle 在其Java 平台标准版 Oracle 提供商文档 ( Java 7/Java 8 ) 中要求:
Cipher suites that use Elliptic Curve Cryptography (ECDSA, ECDH, ECDHE, ECDH_anon) require a JCE cryptographic provider that meets the following requirements:
The provider must implement ECC as defined by the classes and interfaces in the packages java.security.spec and java.security.interfaces. The getAlgorithm() method of elliptic curve key objects must return the string "EC".
The provider must support the Signature algorithms SHA1withECDSA and NONEwithECDSA, the KeyAgreement algorithm ECDH, and a KeyPairGenerator and a KeyFactory for algorithm EC. If one of these algorithms is missing, SunJSSE will not allow EC cipher suites to be used.
The provider must support all the SECG curves referenced in RFC 4492 specification, section 5.1.1 (see also appendix A). In certificates, points should be encoded using the uncompressed form and curves should be encoded using the namedCurve choice, that is, using an object identifier.
If these requirements are not met, EC cipher suites may not be negotiated correctly.
据推测,由于您的代码显式使用“ECDSA”KeyPairGenerator
,原始 key 将“ECDSA”公开为算法,但是当加载序列化表示 BouncyCaSTLe 使用 Oracle 所需的“EC”。
顺便说一下,如果您设置 KEY_ALGORITHM = "EC"
,您将在两个输出中得到“EC”。
关于java - 为什么保存并重新加载 KeyStore 后 Key.getAlgorithm 返回不同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33788331/