结合 keytool 与 Java 签名 / 验证 - 文章教程

结合 keytool 与 Java 签名 / 验证

发布于 2021-04-07 字数 4891 浏览 927 评论 0

参考

密钥对由 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(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 导出的公钥证书,见前文:

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

如果你对这篇文章有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助。

扫码二维码加入Web技术交流群

上一篇:

下一篇:

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

1872 文章
23 评论
32785 人气
更多

推荐作者

qq_pH6xKF

文章 0 评论 0

a3576419

文章 0 评论 0

Meets

文章 0 评论 0

许强

文章 0 评论 0

adao3056

文章 0 评论 0