中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Java結(jié)合keytool實現(xiàn)非對稱簽名與驗證

2018-08-10    來源:importnew

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

參考”Oracle–The Java Tutorials: Generate Keys”
還有姊妹篇:Java結(jié)合keytool實現(xiàn)非對稱加密和解密

keytool的使用

keytool 是 JDK 自帶的一個密鑰庫管理工具。這里只用到了 keytool 的部分功能,包括生成密鑰對、導(dǎo)出公鑰等。keytool 生成的公鑰/私鑰對存放到一個到了一個文件中,這個文件有密碼保護(hù),通稱為 keystore。

生成密鑰對

$ keytool -genkey -alias signLegal -keystore examplestanstore -validity 1800

生成別名為 signLegal 的密鑰對,存放在密鑰庫 examplestanstore 中,證書的有效期是1800天(默認(rèn)是90天)。
輸入一系列的參數(shù)。輸入的參數(shù)遵循了 LDAP 的風(fēng)格和標(biāo)準(zhǔn)?梢韵胂螅傻拿荑對可以看成 LDAP 的一個條目。
命令執(zhí)行成功后會在當(dāng)前目錄下創(chuàng)建一個叫?examplestanstore?的文件。

查看密鑰對

$ keytool -list -keystore examplestanstore -v

列出了examplestanstore密鑰庫的中所有密鑰對。-v參數(shù)表示詳細(xì)信息,詳細(xì)信息中有證書的失效時間。

導(dǎo)出公鑰證書

$ keytool -export -keystore examplestanstore -alias signLegal -file StanSmith.cer

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

Java簽名和驗證

參考了Java安全官方教程。
在該官方教程中,GenSig.java?類生成密鑰對,對輸入的文件進(jìn)行簽名,輸出了一個簽名結(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

在實際使用時,密鑰對不可能每次在程序中重新生成。而 keytool 恰好可以生成并相對安全保存密鑰對。所以下面結(jié)合了 keytool 和 Java 實現(xiàn)的功能。

結(jié)合keytool與Java簽名/驗證

參考”Oracle–The Java Tutorials: Weaknesses and Alternatives”

密鑰對由 keytool 生成并保存到 keystore 中保護(hù)起來(keystore有密碼)。公鑰也從 keystore 中導(dǎo)出。GenSig.java 類只需要從 keystore 中取得私鑰進(jìn)行簽名即可。
VerSig.java 也要做適當(dāng)?shù)男薷。貌似因為?keystore 中導(dǎo)出的是證書而不是公鑰,兩者的封裝格式估計有差異。

具體步驟

  1. 利用?keytool -genkey?生成密鑰對保存在 keystore 中(庫文件是examplestanstore);
  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 進(jìn)行驗證。

下面是 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("examplestanstore");
                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

OpenSSL

雖然也研究了一下 OpenSSL,但發(fā)現(xiàn)與 Java 難以結(jié)合,難度也很大。例如它的教程中采用的是 RSA,而上面的 Java 使用的是 DSA。所以只是貼在這里備忘,可以忽略。

參考”An Introduction to the OpenSSL command line tool”

生成私鑰

$ openssl genrsa -out key.pem 1024
$ cat key.pem
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCzVDmu6Cf2QF7cERCGYU3B8Epm6pkkpMZFgotphXMgAmBBNJbh
Si7qPH4R5JlEm1ZXPr5DZH/pyJBWQhiiHGeUAOve+GOgvt9Rk25r7OEWYvn/GCr/
JBfLBGqwtlzn/t2s2x04IooshsGkOd6YpZoztkEDtu2gKHedFczF607IvwIDAQAB
AoGAMdbIqUmwQYomUvcTJqXIXIwRwYSVx09cI1lisZL7Kfw/ECAzhq19WHAzgXmM
9zpMxraTXluCCVFKfA6mlfda+ZoBlKSYdOecwNB+TSAumf9XK8uHW/g8C+Ykq9OG
g9Uiy8rKnl12Zaiu9H8L82ud0CkTFW2636/PuKgtp+4YbXECQQDhKdh8lwgumg7H
YIw5476QOHnPL7c3OFPGtaOZMZJkjMPfRzgR4B5PjcGnOLDoTlkATcBPmXtLwwJJ
SzaBdaRjAkEAy+NwdOzC1yQrTrkZQx1brNjO3iytfkl3t1xAWyz5Sy1IB7+4fsod
Eh3br5E1o5YRipY2GJZvp2OAAt3tz6iS9QJASvIYwu+qo4hX3vk9847gwTRrJxFk
1JaFHCEdgUJEzf8ku08DVL/alvRCPxzZlZluenFmz5fwuDkCq87DJ7g2rQJBAMDM
+SnIPdMeA8n0pRvfJjLD7pMP4pu6M3fzx3Owiqj5T9TsCjXzQBxCmdxizzs7DKll
tA/6Kek64PFVFa25tgUCQQCTM1VwfNKjFbd+0HuF6WAs3Odjuo0gKk/QIjdn7M5/
I0kxEApKxTto3oiuCQGeYL/sqy3WjM0476w48+xUsQeF
-----END RSA PRIVATE KEY-----

導(dǎo)出公鑰

$ openssl rsa -in key.pem -pubout -out pub-key.pem
$ cat pub-key.pem
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzVDmu6Cf2QF7cERCGYU3B8Epm
6pkkpMZFgotphXMgAmBBNJbhSi7qPH4R5JlEm1ZXPr5DZH/pyJBWQhiiHGeUAOve
+GOgvt9Rk25r7OEWYvn/GCr/JBfLBGqwtlzn/t2s2x04IooshsGkOd6YpZoztkED
tu2gKHedFczF607IvwIDAQAB
-----END PUBLIC KEY-----

摘要計算

創(chuàng)建一個內(nèi)容是?1234?的文本文件 hello.txt。用 OpenSSL 計算它的 SHA256 摘要(SHA256 是 jarsigner 的默認(rèn)摘要算法):

$ cat hello.txt
1234
$ openssl dgst -SHA256 -out hello.sha256 hello.txt
$ cat hello.sha256
SHA256(hello.txt)= a883dafc480d466ee04e0d6da986bd78eb1fdd2178d04693723da3a8f95d42f4

簽名和驗證

對摘要文件 hello.sha256 進(jìn)行簽名:

$ openssl rsautl -sign -in hello.sha256 -out hello.sign -inkey key.pem

用公鑰對簽名進(jìn)行驗證:

$ openssl rsautl -verify -in hello.sign -inkey pub-key.pem -pubin
SHA256(hello.txt)= a883dafc480d466ee04e0d6da986bd78eb1fdd2178d04693723da3a8f95d42f4

用公鑰驗證必須加上?-pubin?參數(shù)。 用私鑰對簽名進(jìn)行驗證:

$ openssl rsautl -verify -in hello.sign -inkey key.pem
SHA256(hello.txt)= a883dafc480d466ee04e0d6da986bd78eb1fdd2178d04693723da3a8f95d42f4

驗證的STD輸出與摘要文件 hello.sha256 的內(nèi)容一樣,說明驗證可以通過。

標(biāo)簽: ssl 安全

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請與原作者聯(lián)系。

上一篇:高效遍歷Java容器

下一篇:Java連接HBase(kerberized集群)