How to retrieve my public and private key from the keystore we created
我的任务如下:
- 从我创建的密钥库中检索我的公钥和私钥。
- 使用这些密钥使用我的RSA 2048位公钥加密段落。
- 使用dsa-sha-1签名算法对结果进行数字签名。
- 将数字签名输出保存在名为
output.dat 的文件中。
下面的程序引发错误:"java.security.invalidkeyException:没有安装的提供程序支持此密钥:sun.security.provider.dsapublickeyimpl"。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import java.security.*; import java.security.KeyStore.*; import java.io.*; import java.security.PublicKey; import java.security.PrivateKey; import javax.crypto.Cipher; import java.nio.charset.*; import sun.security.provider.*; import javax.crypto.*; public class Code { /** * @param args the command line arguments */ public static void main(String[] args) { try { /* getting data for keystore */ File file = new File(System.getProperty("user.home") + File.separatorChar +".keystore"); FileInputStream is = new FileInputStream(file); KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); /*Information for certificate to be generated */ String password ="abcde"; String alias ="mykeys"; String alias1 ="skeys"; String filepath ="C:\\email.txt"; /* getting the key*/ keystore.load(is, password.toCharArray()); PrivateKey key = (PrivateKey)keystore.getKey(alias,"bemylife".toCharArray()); //PrivateKey key = cert1.getPrivateKey(); //PublicKey key1= (PrivateKey)key; /* Get certificate of public key */ java.security.cert.Certificate cert = keystore.getCertificate(alias); /* Here it prints the public key*/ System.out.println("Public Key:"); System.out.println(cert.getPublicKey()); /* Here it prints the private key*/ System.out.println(" Private Key:"); System.out.println(key); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE,cert.getPublicKey()); String cleartextFile ="C:\\email.txt"; String ciphertextFile ="D:\\ciphertextRSA.png"; FileInputStream fis = new FileInputStream(cleartextFile); FileOutputStream fos = new FileOutputStream(ciphertextFile); CipherOutputStream cos = new CipherOutputStream(fos, cipher); byte[] block = new byte[32]; int i; while ((i = fis.read(block)) != -1) { cos.write(block, 0, i); } cos.close(); /* computing the signature*/ Signature dsa = Signature.getInstance("SHA1withDSA","SUN"); dsa.initSign(key); FileInputStream f = new FileInputStream(ciphertextFile); BufferedInputStream in = new BufferedInputStream(f); byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) >= 0) { dsa.update(buffer, 0, len); }; in.close(); /* Here it prints the signature*/ System.out.println("Digital Signature :"); System.out.println( dsa.sign()); /* Now Exporting Certificate */ System.out.println("Exporting Certificate."); byte[] buffer_out = cert.getEncoded(); FileOutputStream os = new FileOutputStream(new File("d:\\signedcetificate.cer")); os.write(buffer_out); os.close(); /* writing signature to output.dat file */ byte[] buffer_out1 = dsa.sign(); FileOutputStream os1 = new FileOutputStream(new File("d:\\output.dat")); os1.write(buffer_out1); os1.close(); } catch (Exception e) {System.out.println(e);} } } |
您必须将它从keystore文件(可能以
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /** * Reads a Java keystore from a file. * * @param keystoreFile * keystore file to read * @param password * password for the keystore file * @param keyStoreType * type of keystore, e.g., JKS or PKCS12 * @return the keystore object * @throws KeyStoreException * if the type of KeyStore could not be created * @throws IOException * if the keystore could not be loaded * @throws NoSuchAlgorithmException * if the algorithm used to check the integrity of the keystore * cannot be found * @throws CertificateException * if any of the certificates in the keystore could not be loaded */ public static KeyStore loadKeyStore(final File keystoreFile, final String password, final String keyStoreType) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { if (null == keystoreFile) { throw new IllegalArgumentException("Keystore url may not be null"); } LOG.debug("Initializing key store: {}", keystoreFile.getAbsolutePath()); final URI keystoreUri = keystoreFile.toURI(); final URL keystoreUrl = keystoreUri.toURL(); final KeyStore keystore = KeyStore.getInstance(keyStoreType); InputStream is = null; try { is = keystoreUrl.openStream(); keystore.load(is, null == password ? null : password.toCharArray()); LOG.debug("Loaded key store"); } finally { if (null != is) { is.close(); } } return keystore; } |
一旦你拥有了
但使用它来签署文本并将其保存到文件中更为复杂,而且很容易出错。使用给定的公钥查看符号字符串,并将
1 2 3 4 5 6 7 8 9 | public static KeyPair getKeyPair(final KeyStore keystore, final String alias, final String password) { final Key key = (PrivateKey) keystore.getKey(alias, password.toCharArray()); final Certificate cert = keystore.getCertificate(alias); final PublicKey publicKey = cert.getPublicKey(); return KeyPair(publicKey, (PrivateKey) key); } |
(显然有点粗糙,我手边没有样本)
问题是DSA密钥不适合RSA加密。您需要一个RSA密钥进行加密,也许您可以将签名算法切换到RSA/SHA1以避免需要两个密钥。
1 2 3 4 5 6 7 8 9 | trusted.load(in, ((PBCApplication) context.getApplicationContext()).getBuildSettings().getCertificatePass()); Enumeration enumeration = trusted.aliases(); while (enumeration.hasMoreElements()) { String alias = (String) enumeration.nextElement(); System.out.println("alias name:" + alias); Certificate certificate = trusted.getCertificate(alias); certificate.getPublicKey(); } |
我没有存储在大脑顶部的Java代码,但是一些一般的检查是:
要将公共证书存储在所需位置吗?特别是,我的记忆是,带有公钥和私钥的证书存储在一个别名下,所以您在其中的两个别名设置看起来很奇怪。尝试将两者存储在同一别名下,并在私钥调用和公钥调用中引用它。
您可以从证书中获得其他内容吗?例如,主题DN或颁发者DN都是证书中必须包含的字段。这为您提供了一个很好的证据,证明证书正按预期阅读。
在几乎任何加密事务中,都要非常小心如何读取文件和传输编码方法。如果您已经创建了文件IO并以一种奇怪的方式从中提取,那么您可能会破坏关键材料的编码。这是最后一件要检查的事情,通常Java和JKS并没有这么糟糕,但是它会发生。同样,要清楚文件的格式-例如,jks文件不同于pkcs 12文件。