工作中需要使用非对称加密RSA来进行消息摘要生产和验证,但无法通过keytool工具来提取私钥。
那怎么获得私钥、公钥?
以Java为例:通过KeyStore类getEntry() 或者getKey()来提取私钥;通过Certificate类getPublicKey()获取公钥。
一.Keytool生成KeyStore文件
-- 生成密码仓库test.store keytool -genkey -v -alias test -dname "CN=test,OU=HE,O=CUI,L=SHENGZHEN,ST=GUANGDONG,C=CN" -keyalg RSA -keysize 2048 -keypass 5201314 -keystore test.store -storepass 5201314 -validity 10000 -storetype JCEKS -- 导出证书test.crt keytool -exportcert -alias test -file test.crt -keystore test.store -storepass 5201314 -rfc -storetype JCEKS
运行后在F盘的Key目录下将产生如下两个文件。
二.生成私钥、公钥
KeyStoreHelper.java
package com.bijian.keystore; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.ObjectOutputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import sun.misc.BASE64Encoder; public class KeyStoreHelper { public static void main(String[] args) throws Exception { String privatePath = "F:/Key/testPri.key"; // 准备导出的私钥 String publicPath = "F:/Key/testPub.key"; // 准备导出的公钥 PrivateKey privateKey = getPrivateKeyFromStore(); createKeyFile(privateKey, privatePath); PublicKey publicKey = getPublicKeyFromCrt(); createKeyFile(publicKey, publicPath); byte[] publicKeyBytes = publicKey.getEncoded(); byte[] privateKeyBytes = privateKey.getEncoded(); String publicKeyBase64 = new BASE64Encoder().encode(publicKeyBytes); String privateKeyBase64 = new BASE64Encoder().encode(privateKeyBytes); System.out.println("publicKeyBase64.length():" + publicKeyBase64.length()); System.out.println("publicKeyBase64:" + publicKeyBase64); System.out.println("privateKeyBase64.length():" + privateKeyBase64.length()); System.out.println("privateKeyBase64:" + privateKeyBase64); } private static PrivateKey getPrivateKeyFromStore() throws Exception { String alias = "test"; // KeyTool中生成KeyStore时设置的alias String storeType = "JCEKS"; // KeyTool中生成KeyStore时设置的storetype char[] pw = "5201314".toCharArray(); // KeyTool中生成KeyStore时设置的storepass String storePath = "F:/Key/test.store"; // KeyTool中已生成的KeyStore文件 storeType = null == storeType ? KeyStore.getDefaultType() : storeType; KeyStore keyStore = KeyStore.getInstance(storeType); InputStream is = new FileInputStream(storePath); keyStore.load(is, pw); // 由密钥库获取密钥的两种方式 // KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(pw)); // return pkEntry.getPrivateKey(); return (PrivateKey) keyStore.getKey(alias, pw); } private static PublicKey getPublicKeyFromCrt() throws CertificateException, FileNotFoundException { String crtPath = "F:/Key/test.crt"; // KeyTool中已生成的证书文件 CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(crtPath); Certificate crt = cf.generateCertificate(in); PublicKey publicKey = crt.getPublicKey(); return publicKey; } private static void createKeyFile(Object key, String filePath) throws Exception { FileOutputStream fos = new FileOutputStream(filePath); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(key); oos.flush(); oos.close(); } }
运行上面的代码后,将在F盘的Key目录下新产生testPub.key、testPri.key公私钥文件。
并在控制台输出如下内容:
到此为止,公私钥已生成。
三.验证上面生成的公私钥
1.私钥加签公钥验签,进行验证
DigestUtil.java
package com.bijian.keystore; public class DigestUtil { /** * 字节转为十六进制字符串 * @param字节 * @return 十六进制字符串 */ public static String byte2hex(byte[] b) { String hs = ""; String stmp = ""; for (int n = 0; b != null && n < b.length; n++) { stmp = (java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs; } /** * 十六进制字符转为字节 * @param 十六进制字符 * @return 字节 */ public static byte[] hex2byte(byte[] b) { if ((b.length % 2) != 0) throw new IllegalArgumentException("byte length is not correct"); byte[] b2 = new byte[b.length / 2]; for (int n = 0; n < b.length; n += 2) { String item = new String(b, n, 2); b2[n / 2] = (byte) Integer.parseInt(item, 16); } return b2; } /** * 字符串转换成十六进制值 * @param bin String 我们看到的要转换成十六进制的字符串 * @return */ public static String bin2hex(String bin) { char[] digital = "0123456789ABCDEF".toCharArray(); StringBuffer sb = new StringBuffer(""); byte[] bs = bin.getBytes(); int bit; for (int i = 0; i < bs.length; i++) { bit = (bs[i] & 0x0f0) >> 4; sb.append(digital[bit]); bit = bs[i] & 0x0f; sb.append(digital[bit]); } return sb.toString(); } }
SignUtil.java
package com.bijian.keystore; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import org.apache.commons.codec.binary.Base64; public class SignUtil { //#priKeyText private final static String priKeyText = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChXmxaPt6Qg+XTiqaCG1cZEKwGPbKy/Qs5xGNx4HotngGUM2n/5FdZtSHZofJWsNUUKpZa+BynhNg0E0Qn4Xrp0WSi+Z5LgDewT7DeA0b5Cky386MEWwc11Asa+SuMiR5XFUjXdWrMQX5E7wVRcbuoq7A8QBfm3i8F4PdMokhlMviwhLngKOrWVKobE8cyA25Jv2FZgxv1NzVZ7zyGaO60a49X/NaA2poe5OB9zXBfsa8kfHl0b+sMQMd38uVrtCIqs2KABW6EGTToezk55i+hHg7nqMLum7Xtw8z/T1fpEtKgsnKANph7eqRHVHmjUDpHidx3BiTAArw07MVIq1LhAgMBAAECggEADJPDdjU4O6NMInTIDZP78eQuxD3C09iNK293IMUSQMPz840eUeeGN2O6w6+vp7oYoX3AQk7cTOI5x7VItqMIZXkAkwNJpzDTJlbPvj4bJgX7fMrshcZihXuFchDBqC53wunRx5lLPahNIypOC88FhVv8XHXSZxgiKh8ip0JuyhRS38TDVCcrIzKclsSY9CT3kYhVdPkfWEEGSb0qj7J4VxK7evE6yQD0/UJqB9j54Ts418DsEHNOZPDf6PFgNgl585AQZ3KpEUrfsx3rygLhUG+GQD+bkkDExA7vJlw5v1CF7Kr1T/XK9gjqRbRBjtzLy0MUe11ips3OM5LYkNv/EQKBgQDuWD+i64alAdXeReJAHWU8sQjZgmZYhlMhxfq8rsalJ490br3joZ2+KHXD7yDmvTUj0IFre99BcB7hi9Sx0joOjyS8+Rz7Bw02bdnwJbva5SYg3XojqdEoKGl5nFN67rL762jGsDG2Y5/hVEe/vxmH9sWB/OvQZ10If3p5OJ/jcwKBgQCtUnl1IWn57xHzqDqQEIMlCskGRXElMYdU/jtADLTt27DgSjzbgW5GgGMectvDDxYADYb93VUuTvz4EvHXAwo3CepDUjs4JtkGZeaAnMCER6doIyXPfRsxHMXRN4NgG70yEA5u7IfYFA1DuGLDwjddg4rU122ftqUM2UcwaaBjWwKBgQC9R9wRuFXPiOudf4Y0QKP7VOSgSAybVOGEOsPrQCmFUyt73c5zjg/Fyj/sAGXymGQxMw70mwUr5KzBldit9zQgB9G3OWaofGsjxI2FR5IuPjjPdNPgqqXt7FoHN/yb7iC6K7Ojxp1UKT35JoNsZYkTDwi/OGrVsKCTdRmAV1WyvQKBgBZD6Qxt/XI5DwJREyzcoixJBWgD1bQkd7Eoc64Xs8p2lXNKtiSwrNzrs0//C1I0huv80OGd5EptpTutG1o2rsJBSNHbJ3ZgLzMONh1Bhc24cr4C/eF4vdyCSLtGuV7IUXaz71a6lfzhHo8bibyCH6CovFX5UsDYsr1C0E1c1FjPAoGAXQ4hZ7/APQ/V1wmkZnplGchbXefqixvhDZWUvIAy6sAmypaRe3fRjd3SFLGXhOg48CQ59A0P3dQjKja8U7eQA6c6qw9Ci4F/cceHcdgnH6fOkqiHMdN6Sr0/SinbVP0kqU25y+AbRdJjwYZGTmWeqMdFUra+MVK9befn+hA3zAk="; //#pubKeyText private final static String pubKeyText = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoV5sWj7ekIPl04qmghtXGRCsBj2ysv0LOcRjceB6LZ4BlDNp/+RXWbUh2aHyVrDVFCqWWvgcp4TYNBNEJ+F66dFkovmeS4A3sE+w3gNG+QpMt/OjBFsHNdQLGvkrjIkeVxVI13VqzEF+RO8FUXG7qKuwPEAX5t4vBeD3TKJIZTL4sIS54Cjq1lSqGxPHMgNuSb9hWYMb9Tc1We88hmjutGuPV/zWgNqaHuTgfc1wX7GvJHx5dG/rDEDHd/Lla7QiKrNigAVuhBk06Hs5OeYvoR4O56jC7pu17cPM/09X6RLSoLJygDaYe3qkR1R5o1A6R4ncdwYkwAK8NOzFSKtS4QIDAQAB"; private final static String CHARACTER_ENCODING_UTF_8 = "UTF-8"; public static void main(String[] args) { String signString = "bijian 您好!"; try { // 加签 String localSignature = SignUtil.sign(priKeyText.getBytes(CHARACTER_ENCODING_UTF_8), signString); System.out.println(localSignature); //验签 boolean verifyResult = SignUtil.verify(pubKeyText.getBytes(CHARACTER_ENCODING_UTF_8), signString, localSignature); System.out.println("verifyResult:" + verifyResult); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * RSA私钥加签 * @param priKeyText经过base64处理后的私钥 * @param plainText明文内容 * @return 十六进制的签名字符串 * @throws Exception */ public static String sign(byte[] priKeyText, String plainText) throws Exception { try { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decodeBase64(priKeyText)); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey prikey = keyf.generatePrivate(priPKCS8); // 用私钥对信息生成数字签名 java.security.Signature signet = java.security.Signature.getInstance("SHA256withRSA"); signet.initSign(prikey); signet.update(plainText.getBytes("UTF-8")); return DigestUtil.byte2hex(signet.sign()); } catch (Exception e) { throw e; } } /** * 公钥验签 * @param pubKeyText经过base64处理后的公钥 * @param plainText明文内容 * @param signText十六进制的签名字符串 * @return 验签结果 true验证一致 false验证不一致 */ public static boolean verify(byte[] pubKeyText, String plainText, String signText) { try { // 解密由base64编码的公钥,并构造X509EncodedKeySpec对象 java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec( Base64.decodeBase64(pubKeyText)); // RSA算法 java.security.KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA"); // 取公钥匙对象 java.security.PublicKey pubKey = keyFactory.generatePublic(bobPubKeySpec); // 十六进制数字签名转为字节 byte[] signed = DigestUtil.hex2byte(signText.getBytes("UTF-8")); java.security.Signature signatureChecker = java.security.Signature.getInstance("SHA256withRSA"); signatureChecker.initVerify(pubKey); signatureChecker.update(plainText.getBytes("UTF-8")); // 验证签名是否正常 return signatureChecker.verify(signed); } catch (Throwable e) { return false; } } }
运行结果如下,验签通过。
2.将F:\Key下生成公私钥验证加解密
将F:\Key下的testPub.key、testPri.key拷贝至工程中
运行如下代码
package com.bijian.keystore; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.security.Key; import javax.crypto.Cipher; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class RSAUtil2 { /** 指定加密算法为RSA */ private static final String ALGORITHM = "RSA"; /** 指定公钥存放文件 */ private static String PUBLIC_KEY_FILE = "testPub.key"; /** 指定私钥存放文件 */ private static String PRIVATE_KEY_FILE = "testPri.key"; public static void main(String[] args) throws Exception { String source = "深圳,你好!";// 要加密的字符串 System.out.println("准备用公钥加密的字符串为:" + source); String cryptograph = encrypt(source);// 生成的密文 System.out.print("用公钥加密后的结果为:" + cryptograph); System.out.println(); String target = decrypt(cryptograph);// 解密密文 System.out.println("用私钥解密后的字符串为:" + target); System.out.println(); } /** * 加密方法 * @param source 源数据 * @return * @throws Exception */ public static String encrypt(String source) throws Exception { Key publicKey = getKey(PUBLIC_KEY_FILE); /** 得到Cipher对象来实现对源数据的RSA加密 */ Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] b = source.getBytes(); /** 执行加密操作 */ byte[] b1 = cipher.doFinal(b); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(b1); } /** * 解密算法 * @param cryptograph 密文 * @return * @throws Exception */ public static String decrypt(String cryptograph) throws Exception { Key privateKey = getKey(PRIVATE_KEY_FILE); /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */ Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, privateKey); BASE64Decoder decoder = new BASE64Decoder(); byte[] b1 = decoder.decodeBuffer(cryptograph); /** 执行解密操作 */ byte[] b = cipher.doFinal(b1); return new String(b); } private static Key getKey(String fileName) throws Exception, IOException { Key key; ObjectInputStream ois = null; try { /** 将文件中的私钥对象读出 */ ois = new ObjectInputStream(new FileInputStream(fileName)); key = (Key) ois.readObject(); } catch (Exception e) { throw e; } finally { ois.close(); } return key; } }
运行结果:
附:sun.misc.BASE64Encoder找不到jar包的解决方法
在MyEclipse中编写Java代码时,用到了BASE64Decoder,import sun.misc.BASE64Decoder;可是Eclipse提示:
Access restriction: The type BASE64Decoder is not accessible due to restriction on required library C:\Program
files\java\jre6\lib\rt.jar
Access restriction : The constructor BASE64Decoder() is not accessible due to restriction on required library C:\Program files\java\jre6\lib\rt.jar
解决方案1(推荐):
只需要在project build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
解决方案2:
右键项目->属性->Java bulid path->jre System Library->access rules->resolution选择accessible,下面填上**,点击确定即可!!!
参考文章:http://jingyan.baidu.com/article/f3e34a12ad7acff5ea653569.html
附阿里生成公私钥的链接:https://docs.open.alipay.com/291/105971
相关推荐
Java_keytool密钥存储文件是使用Java_keytool工具生成服务器配置SSL使用的密钥存储文件。该文件是一个容器,用于存储密钥和证书,它是SSL/TLS加密协议的基础组件。本文将详细介绍生成密钥存储文件、产生SSL证书请求...
Java代码验证keytool工具生成的密钥...总的来说,理解并熟练使用keytool生成和验证密钥对是Java开发者必备的技能之一,它关乎到应用程序的安全性和合规性。通过学习和实践,你可以更好地掌控这些核心的加密和认证技术。
1. 密钥对生成:源码会包含生成RSA或DSA等加密算法的公钥和私钥对的逻辑。 2. 密钥库管理:Keytool-IUI需要能够创建、打开、修改和删除JKS(Java Keystore)或PKCS12格式的密钥库。 3. 证书操作:源码会涉及证书的...
使用这些文件,用户可以方便地在Java程序中生成RSA密钥对,而无需手动运行`keytool`命令。这对于自动化证书管理和部署流程特别有用,特别是在服务器配置、HTTPS通信或安全的数据交换中。 在实际应用中,非对称加密...
在本文中,我们将深入探讨KeyTool的基本用法、X.509证书的概念,以及如何使用KeyTool生成这种类型的证书。 X.509是一种国际标准,用于定义证书的格式,它包含了公钥和相关标识信息,如组织名称、地理位置等,常用于...
Keytool是Java平台上的一个标准工具,用于生成、存储和管理密钥对以及数字证书。它在Java安全框架中扮演着核心角色,支持SSL/TLS协议,确保网络通信的安全。通过使用Keytool,开发者可以创建本地密钥库,生成公钥和...
使用Keytool生成自签名证书和密钥对的命令如下: ``` keytool -genkeypair -alias <别名> -keyalg RSA -keystore <密钥库文件名> -keysize <密钥长度> ``` 其中,`<别名>`是证书的唯一标识,`<密钥库文件名>`是...
3. **生成密钥对**:Keytool可以生成RSA或DSA等类型的密钥对,用于加密和解密数据。 4. **查看Keystore信息**:显示Keystore中的所有条目,包括证书的详细信息。 5. **更改Keystore密码**:保护Keystore的安全,可以...
- **生成私钥**:使用`openssl genpkey`命令可以生成RSA或ECDSA等类型的私钥,如`openssl genpkey -algorithm RSA -out private.key`生成一个RSA私钥。 - **生成CSR**:私钥生成后,利用`openssl req`命令创建CSR...
- 首先,使用`KeyPairGenerator`实例化一个RSA密钥对生成器,并设置密钥长度(例如2048位)。 - 然后,调用`generateKeyPair()`方法生成密钥对。 - 接着,创建`X509CertInfo`对象,包含证书的基本信息,如主体...
`keytool1.6`是Java早期版本中的一个核心工具,虽然它的功能相对有限,但在生成签名文件和管理密钥库方面仍然发挥着作用。然而,为了保持最佳的安全实践,开发者应考虑升级到更现代的版本,并遵循最新的加密标准和...
**Keytool** 是 Java 开发工具包(JDK)中的一个实用程序,用于管理密钥库(key stores),其中包括私钥(private keys)及其对应的公钥证书(public key certificates)。密钥库是一个存储密钥和证书的地方,可以用来管理和...
`keytool`是Java开发工具包(JDK)的一部分,主要功能是管理和操作密钥对和数字证书。这个工具在Linux和其他操作系统上广泛用于安全配置,特别是在构建HTTPS服务器、SSL/TLS连接以及进行数字签名等方面。以下是关于`...
总之,`JAVA keytool`数字证书生成及应用是一个涵盖密钥对管理、证书创建、导入导出、以及安全配置等多个方面的重要话题。了解并熟练掌握这些操作,可以帮助开发者确保Java应用程序的安全性,并有效地进行网络通信的...
这段代码展示了如何在Java中生成RSA密钥对以及如何使用公钥加密、私钥解密。在文件传输中,发送方可以用接收方的公钥加密文件,确保即使在网络中被截获,也无法直接读取文件内容,只有拥有对应私钥的接收方才能解密...
`keytool` 是 Java 提供的一个强大的命令行工具,用于管理和维护 Java 应用程序的安全性,特别是密钥和证书方面。它允许用户创建、导入、导出、查看和删除密钥库中的证书。这些操作对于开发安全的应用程序至关重要。...
Java KeyTool 使用指南 Java KeyTool 是 Java 安全套件中的一部分,用于创建、管理和维护数字证书。下面是使用 KeyTool 的详细...通过使用 KeyTool,可以轻松地生成密钥对、导出证书、将证书导入 Java 信任证书库等。
在KeyTool中,用户可以生成一对RSA密钥,用于服务器的身份验证和数据加密。 ### 三、服务器证书 服务器证书是网络服务器身份的证明,它包含服务器的公钥、服务器的标识信息(如域名)、证书颁发机构(CA)的签名等...
生成Android签名文件通常使用Java的`keytool`命令行工具,它包含在Java Development Kit (JDK) 中。以下是基本的生成流程: 1. 运行`keytool -genkeypair`命令,指定输出的keystore文件名、密码以及开发者信息(如...