Java之keytool非對稱簽名與驗證

本文參考

什么是keytool注整?
keytool是JDK自帶的一個密鑰庫管理工具能曾。這里只用到了keytool的部分功能度硝,包括生成密鑰對,導(dǎo)出公鑰等寿冕。keytool生成的公鑰/私鑰對存放到一個到了一個文件中蕊程,這個文件有密碼保護,通稱為keystore蚂斤。

生成密鑰對

$ keytool -genkeypair \
-alias config-server \
-keystore config-server.keystore \
-validity 1800 \
-keyalg RSA \
-dname "CN=yxx, OU=company, O=org, L=city, ST=province, C=china" \
-keypass 222222 \
-storepass 111111

上面是創(chuàng)建密鑰對的命令,具體參數(shù)如下:
*alias 別名
*keystore 密鑰庫名稱
*validity 有效時間
*keyalg 密鑰對方式
*dname 基本信息
*keypass 密鑰口令
*storepass 密鑰庫口令
執(zhí)行上面的命令槐沼,會有一個提示曙蒸,如下:

JKS 密鑰庫使用專用格式。
建議使用 "keytool -importkeystore -srckeystore config-server.keystore 
-destkeystore config-server.keystore -deststoretype pkcs12" 遷移到行業(yè)標(biāo)準(zhǔn)格式 PKCS12岗钩。

可以根據(jù)自己的情況看是否需要轉(zhuǎn)P12纽窟。

查看密鑰對

$ keytool -list -keystore examplestanstore -v

列出了config-server.keystore密鑰庫的中所有密鑰對。-v參數(shù)表示詳細(xì)信息兼吓,詳細(xì)信息中有證書的失效時間臂港。

導(dǎo)出公鑰證書

$ keytool -export -keystore config-server.keystore \
-alias config-server -file config-server.cer

導(dǎo)出的公鑰存放在當(dāng)前目錄的StanSmith.cer文件中,是個二進制文件视搏。

java簽名和驗證
參考了java安全官方教程审孽。
在該官方教程中,GenSig.java類生成密鑰對浑娜,對輸入的文件進行簽名佑力,輸出了一個簽名結(jié)果文件sig和公鑰suepk。
VerSig.java類接受三個參數(shù):公鑰文件名(suepk)筋遭、簽名文件(sig)打颤、被簽名的源文件名(hello.txt)。
該教程解釋了兩個類的原理漓滔,并附加有源碼。將源碼下載并編譯透且。創(chuàng)建一個hello.txt的文件作為被簽名的目標(biāo)文件豁鲤,里面隨便放點字符串畅形。然后執(zhí)行:

$ java GenSig hello.txt                        (生成文件sig和suepk)
$ java VerSig suepk sig hello.txt
signature verifies: true

注意:上面的代碼在一個單獨目錄中執(zhí)行
在實際使用時,密鑰對不可能每次在程序中重新生成棍厌。而keytool恰好可以生成并相對安全保存密鑰對耘纱。所以下面結(jié)合了keytool和java實現(xiàn)的功能。

結(jié)合keytool與java簽名/驗證
密鑰對由keytool生成并保存到keystore中保護起來(keystore有密碼)艳馒。公鑰也從keystore中導(dǎo)出弄慰。GenSig.java類只需要從keystore中取得私鑰進行簽名即可蝶锋。
VerSig.java也要做適當(dāng)?shù)男薷摹C菜埔驗閺膋eystore中導(dǎo)出的是證書而不是公鑰慌闭,兩者的封裝格式估計有差異驴剔。

具體步驟
1.利用keytool -genkey生成密鑰對保存在keystore中(庫文件是config-server.keystore)
2.利用`keytool -export’從keystore中導(dǎo)出公鑰證書(StanSmith.cer)
3.利用新類GenSig2.java生成簽名(文件名是sig)粥庄,GenSig2.java會從keystore中取私鑰
4.將公鑰(StanSmith.cer)飒赃、簽名(sig)、被簽名文件(hello.txt)發(fā)給驗證方
5.驗證方利用VerSig2.java進行驗證
下面是GenSig2.java和VerSig2.java的源碼和執(zhí)行方式炒事。
GenSig2.java

import java.io.*;
import java.security.*;

class GenSig2 {

    public static void main(String[] args) {

        if (args.length != 1) {
            System.out.println("Usage: java GenSig2 <nameOfFileToSign>");
            }
        else try{

                /*create key paire use keytool:
                $ keytool -genkey -alias signLegal -keystore examplestanstore -validity 1800*/
                // read keystore file
                KeyStore ks = KeyStore.getInstance("JKS");
                FileInputStream ksfis = new FileInputStream("config-server.keystore");
                BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

                // open keystore and get private key
                // alias is 'signLeal', kpasswd/spasswd is 'vagrant'
                ks.load(ksbufin, "vagrant".toCharArray());
                PrivateKey priv = (PrivateKey) ks.getKey("signLegal", "vagrant".toCharArray());

            /* Create a Signature object and initialize it with the private key */

            Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

            dsa.initSign(priv);
            /* Update and sign the data */

            FileInputStream fis = new FileInputStream(args[0]);
            BufferedInputStream bufin = new BufferedInputStream(fis);
            byte[] buffer = new byte[1024];
            int len;
            while (bufin.available() != 0) {
                len = bufin.read(buffer);
                dsa.update(buffer, 0, len);
                };

            bufin.close();

            /* Now that all the data to be signed has been read in,
                    generate a signature for it */
            byte[] realSig = dsa.sign();

            /* Save the signature in a file */
            FileOutputStream sigfos = new FileOutputStream("sig");
            sigfos.write(realSig);

            sigfos.close();

            /* public key file can export from keystore use keytool:
            $  keytool -export -keystore examplestanstore -alias signLegal -file StanSmith.cer */

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    };

編譯后,這樣運行:

$ java GenSig2 hello.txt

會生成簽名文件sig姑躲。

VerSig2.java

import java.io.*;
import java.security.*;
import java.security.spec.*;

class VerSig2 {

    public static void main(String[] args) {

        /* Verify a DSA signature */

        if (args.length != 3) {
            System.out.println("Usage: VerSig publickeyfile signaturefile datafile");
            }
        else try{

            /* import encoded public cert */
            FileInputStream certfis = new FileInputStream(args[0]);
            java.security.cert.CertificateFactory cf =
                java.security.cert.CertificateFactory.getInstance("X.509");
            java.security.cert.Certificate cert =  cf.generateCertificate(certfis);
            PublicKey pubKey = cert.getPublicKey();

            /* input the signature bytes */
            FileInputStream sigfis = new FileInputStream(args[1]);
            byte[] sigToVerify = new byte[sigfis.available()];
            sigfis.read(sigToVerify );

            sigfis.close();

            /* create a Signature object and initialize it with the public key */
            Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
            sig.initVerify(pubKey);

            /* Update and verify the data */

            FileInputStream datafis = new FileInputStream(args[2]);
            BufferedInputStream bufin = new BufferedInputStream(datafis);
            byte[] buffer = new byte[1024];
            int len;
            while (bufin.available() != 0) {
                len = bufin.read(buffer);
                sig.update(buffer, 0, len);
                };

            bufin.close();

            boolean verifies = sig.verify(sigToVerify);

            System.out.println("signature verifies: " + verifies);

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        };
    }
}

編譯后卖怜,這樣運行(StanSmith.cer是利用keytool導(dǎo)出的公鑰證書马靠,見前文):

$ java VerSig2 StanSmith.cer sig hello.txt
signature verifies: true

學(xué)習(xí)交流,請加群:64691032

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逞度,一起剝皮案震驚了整個濱河市档泽,隨后出現(xiàn)的幾起案子揖赴,更是在濱河造成了極大的恐慌,老刑警劉巖甜熔,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突倍,死亡現(xiàn)場離奇詭異羽历,居然都是意外死亡淡喜,警方通過查閱死者的電腦和手機炼团,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門瘟芝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锌俱,你說我怎么就攤上這事≡烨蓿” “怎么了吭练?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵鲫咽,是天一觀的道長叫榕。 經(jīng)常有香客問我晰绎,道長,這世上最難降的妖魔是什么荞下? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任尖昏,我火速辦了婚禮构资,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迹淌。我一直安慰自己己单,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布纹份。 她就那樣靜靜地躺著蔓涧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪元暴。 梳的紋絲不亂的頭發(fā)上鳞陨,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天厦滤,我揣著相機與錄音,去河邊找鬼掏导。 笑死,一個胖子當(dāng)著我的面吹牛趟咆,可吹牛的內(nèi)容都是我干的梅屉。 我是一名探鬼主播坯汤,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼搀愧,長吁一口氣:“原來是場噩夢啊……” “哼咱筛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起溉愁,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤拐揭,失蹤者是張志新(化名)和其女友劉穎篙贸,沒想到半個月后枫疆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡寝贡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年圃泡,在試婚紗的時候發(fā)現(xiàn)自己被綠了愿险。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡风秤,死狀恐怖扮叨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情彻磁,我是刑警寧澤狸捅,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布尘喝,位于F島的核電站瞧省,受9級特大地震影響鳍贾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骑科,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一咆爽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧符糊,春花似錦呛凶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽殷蛇。三九已至,卻和暖如春亮航,著一層夾襖步出監(jiān)牢的瞬間谍倦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工宴猾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留仇哆,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓油讯,卻偏偏與公主長得像延欠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子由捎,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容