设为首页 加入收藏

TOP

Java结合keytool实现非对称签名与验证(一)
2018-08-10 09:12:10 】 浏览:48
Tags:Java 结合 keytool 实现 对称 签名 验证

参考”Oracle–The Java Tutorials: Generate Keys”
还有姊妹篇:Java结合keytool实现非对称加密和解密

keytool的使用

keytool 是 JDK 自带的一个密钥库管理工具。这里只用到了 keytool 的部分功能,包括生成密钥对、导出公钥等。keytool 生成的公钥/私钥对存放到一个到了一个文件中,这个文件有密码保护,通称为 keystore。

生成密钥对

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

生成别名为 signLegal 的密钥对,存放在密钥库 examplestanstore 中,证书的有效期是1800天(默认是90天)。
输入一系列的参数。输入的参数遵循了 LDAP 的风格和标准。可以想象,生成的密钥对可以看成 LDAP 的一个条目。
命令执行成功后会在当前目录下创建一个叫 examplestanstore 的文件。

查看密钥对

$ keytool -list -keystore examplestanstore -v

列出了examplestanstore密钥库的中所有密钥对。-v参数表示详细信息,详细信息中有证书的失效时间。

导出公钥证书

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

导出的公钥存放在当前目录的 StanSmith.cer 文件中,是个二进制文件。

Java签名和验证

参考了Java安全官方教程
在该官方教程中,GenSig.java 类生成密钥对,对输入的文件进行签名,输出了一个签名结果文件 sig 和公钥 suepk。
VerSig.java 类接受三个参数:公钥文件名(suepk)、签名文件(sig)、被签名的源文件名(hello.txt)。
该教程解释了两个类的原理,并附加有源码。将源码下载并编译。创建一个 hello.txt 的文件作为被签名的目标文件,里面随便放点字符串。然后执行:

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

在实际使用时,密钥对不可能每次在程序中重新生成。而 keytool 恰好可以生成并相对安全保存密钥对。所以下面结合了 keytool 和 Java 实现的功能。

结合keytool与Java签名/验证

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

密钥对由 keytool 生成并保存到 keystore 中保护起来(keystore有密码)。公钥也从 keystore 中导出。GenSig.java 类只需要从 keystore 中取得私钥进行签名即可。
VerSig.java 也要做适当的修改。貌似因为从 keystore 中导出的是证书而不是公钥,两者的封装格式估计有差异。

具体步骤

  1. 利用 keytool -genkey 生成密钥对保存在 keystore 中(库文件是examplestanstore);
  2. 利用 `keytool -export` 从 keystore 中导出公钥证书(StanSmith.cer);
  3. 利用新类 GenSig2.java 生成签名(文件名是sig),GenSig2.java 会从 keystore 中取私钥;
  4. 将公钥(StanSmith.cer)、签名(sig)、被签名文件(hello.txt)发给验证方;
  5. 验证方利用 VerSig2.java 进行验证。

下面是 GenSig2.java 和 VerSig2.java 的源码和执行方式。

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(rea
编程开发网
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇高效遍历Java容器 下一篇JDK源码阅读:ByteBuffer

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

最新文章

热门文章

C 语言

C++基础

windows编程基础

linux编程基础

C/C++面试题目