`

Java&keytool生成RSA密钥

阅读更多

        工作中需要使用非对称加密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

  • 大小: 43.8 KB
  • 大小: 32.1 KB
  • 大小: 58.7 KB
  • 大小: 5.9 KB
  • 大小: 1.6 KB
  • 大小: 11 KB
  • 大小: 12.6 KB
分享到:
评论
1 楼 wuhenliushui 2018-03-31  
公钥能改成cer格式么

相关推荐

    java密钥生成工具

    调用keytool自动生成密钥, 包括rsa密钥定义和一个调用可执行文件的类

    java代码生成数字证书

    实现java代码生成cer证书文件,然后可以通过代码获取 不通过keytool工具。生成密钥对。使用公钥加密。

    KeyTool1.6

    Java密钥管理体系工具,生成RSA公私钥以及服务器证书

    keystore-explorer:KeyStore Explorer是Java命令行实用程序keytool和jarsigner的免费GUI替代品

    生成具有自签名X.509证书的RSA,ECC和DSA密钥对 将X.509证书扩展名应用于生成的密钥对和证书签名请求(CSR) 查看X.509证书,CRL和CRL条目X.509 V3扩展 以多种格式导入和导出密钥和证书:PKCS#12,PKCS#8,PKCS#...

    ssl_server_client_poc:了解SSLServerSocket,SSLSocket,Keytool,TrustStore等

    ssl_server_client_poc 了解SSLServerSocket,SSLSocket,Keytool,TrustStore等生成Java密钥库和密钥对keytool -genkey -alias mydomain -keyalg RSA -keystore sample.jks -storepass 123456 为现有的Java密钥库...

    JAVA上百实例源码以及开源项目

     关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥...

    JAVA上百实例源码以及开源项目源代码

     关于数字签名:产生RSA密钥对(myKeyPair),得到RSA密钥对,产生Signature对象,对用私钥对信息(info)签名,用指定算法产生签名对象,用私钥初始化签名对象,将待签名的数据传送给签名对象(须在初始化之后),用公钥...

    keytool.exe

    apk签名用的签名资源文件,基于keytool -genkey -alias abc.keystore -keyalg RSA -validity 20000 -keystore abc.keystore 可生成密钥

    SSL配置手册

    生成keystore文件 生成密钥库文件keystore.jks需要使用JDK的keytool工具。命令行进入JDK下的bin目录运行keytool命令 keytool -genkey -alias server -keyalg RSA -keysize 1024 -keystore keystore.jks -...

    SSL转换工具jks2pfx

    1、利用java自带命令生成密钥: keytool -genkey -v -alias pan2.share888.top -keyalg RSA -keystore d:\local.keystore -validity 36500 2、转换: JKS2PFX D:\local.keystore 123456 pan2.share888.top export...

    cassso:使用cas框架来实现统一登录(单点登录)功能

    a, 用java工具keytool生成用户身份证书 keytool -genkey -alias cobee -keyalg RSA -keystore d:/caskey/cobeekey(不创建文件夹, cobeekey是一个文件) 密钥库口令:123456 cobee密钥口令:666666 b, 导出证书 ...

    RN在Android打包发布App(详解)

    你可以用keytool命令生成一个私有密钥。在Windows上keytool命令放在JDK的bin目录中(比如C:\Program Files\Java\jdkx.x.x_x\bin),你可能需要在命令行中先进入那个目录才能执行此命令。在mac上,直接进入项目根目录...

    android-release-playground:用于测试发布过程的几乎为空的应用程序

    要构建未签名的发行版APK,请运行: ./gradlew app:asR -Punsigned -PreleaseVersionNames=true要生成一个包含2048位RSA密钥对的新JKS文件,请运行: keytool -genkeypair \-keystore debug.jks \-storetype jks \-...

    test-security

    生成一对密钥,该密钥存储在密钥库的单个条目中keytool -genkeypair -alias "foo" -dname CN=a -keystore src/main/resources/keystore.jks -storepass password -keypass password -keyalg RSA -sigalg SHA256...

    forgeide:锻造集成开发环境

    keytool 实用程序以生成新的密钥库文件: keytool -genkey -alias forgeide -keyalg RSA -keystore forgeide.keystore -validity 10950 回答 keytool 向导提示的问题 - 以下仅作为示例提供: 输入密钥库密码:secret...

    spring-boot-2-oauth2-authorization-jwt:带有用户和客户端数据库(JPA,Hibernate,MySQL)的Spring Boot 2 OAuth2 JWT授权服务器实现

    该命令将生成一个名为jwt.jks的文件,其中包含公用密钥和专用密钥。 建议迁移到PKCS12 。 为此,请执行以下命令: keytool -importkeystore -srckeystore jwt.jks -destkeystore jwt.jks -des

    SSL_connection:带有自签名证书的 SSL 连接

    它可以使用命令生成:它可以在我们的服务器应用程序的 /src/main/resources 中使用以下示例命令生成: keytool -genkey -alias serverca -keyalg RSA -keystore keystore.jks -validity 30Validity 参数是证书有效...

    naushad-sbx-test1

    首次生成密钥库(用于本地 SSL 支持) &gt; keytool -keystore keystore -alias jetty -genkey -keyalg RSA Enter keystore password: 123456 Re-enter new password: 123456 What is your first and last n

Global site tag (gtag.js) - Google Analytics