天天看點

Java&keytool生成RSA密鑰

參考文章:http://jingyan.baidu.com/article/f3e34a12ad7acff5ea653569.html

          http://bijian1013.iteye.com/blog/2339874

工作中需要使用非對稱加密rsa來進行消息摘要生産和驗證,但無法通過keytool工具來提取私鑰。

        那怎麼獲得私鑰、公鑰?

        以java為例:通過keystore類getentry() 或者getkey()來提取私鑰;通過certificate類getpublickey()擷取公鑰。

一.keytool生成keystore檔案

cmd代碼  

Java&keytool生成RSA密鑰

--  生成密碼倉庫test.store  

eytool -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  

eytool -exportcert -alias test -file test.crt -keystore test.store -storepass 5201314 -rfc -storetype jceks  

        運作後在f盤的key目錄下将産生如下兩個檔案。

Java&keytool生成RSA密鑰

二.生成私鑰、公鑰

keystorehelper.java

java代碼  

Java&keytool生成RSA密鑰

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公私鑰檔案。

Java&keytool生成RSA密鑰

        并在控制台輸出如下内容:

Java&keytool生成RSA密鑰

        到此為止,公私鑰已生成。

三.驗證上面生成的公私鑰

1.私鑰加簽公鑰驗簽,進行驗證

digestutil.java

Java&keytool生成RSA密鑰

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;  

        return sb.tostring();  

signutil.java

Java&keytool生成RSA密鑰

import java.security.keyfactory;  

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 {  

            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());  

            throw e;   

     * 公鑰驗簽 

     * @param pubkeytext經過base64處理後的公鑰 

     * @param signtext十六進制的簽名字元串 

     * @return 驗簽結果 true驗證一緻 false驗證不一緻 

    public static boolean verify(byte[] pubkeytext, string plaintext, string signtext) {  

            // 解密由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;  

        運作結果如下,驗簽通過。

Java&keytool生成RSA密鑰

2.将f:\key下生成公私鑰驗證加解密

        将f:\key下的testpub.key、testpri.key拷貝至工程中

Java&keytool生成RSA密鑰

        運作如下代碼

Java&keytool生成RSA密鑰

import java.io.ioexception;  

import java.io.objectinputstream;  

import java.security.key;  

import javax.crypto.cipher;  

import sun.misc.base64decoder;  

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";  

        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 源資料 

     * @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    密文 

    public static string decrypt(string cryptograph) throws exception {  

        key privatekey = getkey(private_key_file);  

        /** 得到cipher對象對已用公鑰加密的資料進行rsa解密 */  

        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;  

            /** 将檔案中的私鑰對象讀出 */  

            ois = new objectinputstream(new fileinputstream(filename));  

            key = (key) ois.readobject();  

            throw e;  

        } finally {  

            ois.close();  

        return key;  

        運作結果:

Java&keytool生成RSA密鑰

附: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

Java&keytool生成RSA密鑰

解決方案1(推薦): 

        隻需要在project build path中先移除jre system library,再添加庫jre system library,重新編譯後就一切正常了。 

解決方案2:

        右鍵項目->屬性->java bulid path->jre system library->access rules->resolution選擇accessible,下面填上**,點選确定即可!!!

Java&keytool生成RSA密鑰

大小: 43.8 kb

Java&keytool生成RSA密鑰

大小: 32.1 kb

Java&keytool生成RSA密鑰

大小: 58.7 kb

Java&keytool生成RSA密鑰

大小: 5.9 kb

Java&keytool生成RSA密鑰

大小: 1.6 kb

Java&keytool生成RSA密鑰

大小: 11 kb

Java&keytool生成RSA密鑰