Java 如何从我们创建的密钥库中检索我的公钥和私钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19937890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to retrieve my public and private key from the keystore we created
提问by Zack Ef
My task is the following:
我的任务如下:
- Retrieve my public and private key from the keystore I created.
- Use these keys to encrypt a paragraph using my RSA 2048-bit public key.
- Digitally sign the result using the DSA-SHA-1 signature algorithm.
- Save the digital signature output on a file called
output.dat
.
- 从我创建的密钥库中检索我的公钥和私钥。
- 使用这些密钥使用我的 RSA 2048 位公钥加密一个段落。
- 使用 DSA-SHA-1 签名算法对结果进行数字签名。
- 将数字签名输出保存在名为
output.dat
.
The program below is throwing error : "java.security.InvalidKeyException: No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl".
下面的程序抛出错误:“java.security.InvalidKeyException:没有安装的提供程序支持此密钥:sun.security.provider.DSAPublicKeyImpl”。
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("\nPrivate 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);}
}
}
采纳答案by Drunix
The problem is that a DSA key is unsuitable for RSA encryption. You need an RSA key for encryption, maybe you can switch your signature algorithm to RSA/SHA1 to avoid the need for two keys..
问题是 DSA 密钥不适合 RSA 加密。您需要一个 RSA 密钥进行加密,也许您可以将您的签名算法切换为 RSA/SHA1 以避免需要两个密钥。
回答by CoverosGene
You have to read it from the keystore file (which probably ends in .jks
) into a java.security.KeyStoreobject.
您必须将它从密钥库文件(可能以 结尾.jks
)读取到java.security.KeyStore对象中。
/**
* 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;
}
Once you have the KeyStore
, you can get to the Certificate
and the public and private keys.
拥有 后KeyStore
,您就可以访问Certificate
以及公钥和私钥。
But using that to sign text and save it in a file is more involved, and easy to do wrong. Take a look at Sign string using given Public Keyand replace the getKeyPair
method with one that uses the KeyStore
. Something along the lines of
但是使用它来签署文本并将其保存在文件中更复杂,并且容易出错。查看使用给定公钥的 Sign 字符串,并将该getKeyPair
方法替换为使用KeyStore
. 类似的东西
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);
}
(obviously a little rougher, I didn't have a sample handy)
(显然有点粗糙,我手头没有样品)
回答by bethlakshmi
I don't have the Java code stored at the top of my brain, but some general sanity checks are:
我没有将 Java 代码存储在我的大脑顶部,但一些常规的健全性检查是:
is the public certificate you want stored where you want it? In particular, my recollection is that the certificate with the public key and the private key are stored together under a single alias, so the two alias setting you have there seems really odd. Try storing both under the same alias and referencing it in both the private and public key calls.
can you get anything else out of the certificate - for example, subject DN or issuer DN are both must-have fields in a certificate. That gives you a good proof that the certificate is being read as expected.
in almost any crypto transaction, be very careful with how you read from files and transfer your encoding methods. If you've created your File IO and pulled from it in a weird way, you can corrupt the encoding of the key material. That's a last thing to check - usually Java and JKS haven't been so bad for this, but it happens. On the same vein, be clear about the format of the file - JKS files are different from PKCS 12 files, for example.
您想要的公共证书是否存储在您想要的位置?特别是,我记得带有公钥和私钥的证书存储在一个别名下,所以你在那里的两个别名设置看起来很奇怪。尝试将两者存储在相同的别名下,并在私钥和公钥调用中引用它。
您能从证书中获得其他任何内容吗?例如,主题 DN 或颁发者 DN 都是证书中的必备字段。这为您提供了一个很好的证据,证明正在按预期读取证书。
在几乎所有的加密交易中,从文件读取和传输编码方法的方式都要非常小心。如果您创建了 File IO 并以一种奇怪的方式从中提取,则可能会破坏密钥材料的编码。这是最后要检查的事情 - 通常 Java 和 JKS 对此并没有那么糟糕,但它确实发生了。同样,请清楚文件的格式 - 例如,JKS 文件不同于 PKCS 12 文件。
回答by chavanNil
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();
}