使用keytool生成keystore密钥文件,并提取公钥和私钥,签名、验签。

1、使用生成keystore,路径d:/wymtest.keystore,如果不存在,自动创建;如果存在,则在其中添加
C:\Users>keytool -genkey -alias test11 -keyalg RSA -keysize 1024 -keystore d:/wymtest.keystore -validity 4000

使用keytool生成keystore密钥文件,并提取公钥和私钥,签名、验签。_第1张图片
-validity参数可以指定所创建的证书有效期是多少天
-alias test11指定别名;当密钥库中有多个公钥/私钥对和证书时,应该使用别名,同一个密钥库中可以存放多个条目(公钥/私钥对和证书),它们在密钥库中以别名(alias)区分。
比如:这里如果再次使用test11别名执行一次的话,报错:keytool错误: java.lang.Exception: 没有创建键值对,别名 已经存在

当密钥库中只有一个密钥对别名时,可以使用jdk中的方法获取别名,然后进行加解密;
但是,如果密钥库中存在多个别名的话,由于无法区别该别名属于哪个密钥对,所以不要使用此方法

        FileInputStream is = new FileInputStream(new File("d:\\wymtest.keystore"));
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(is, "123456".toCharArray());
                Enumeration aliasEnum = keyStore.aliases();
        String keyAlias = "" ;
        while (aliasEnum.hasMoreElements()) {
             keyAlias = (String) aliasEnum.nextElement();
            System.out.println("别名"+keyAlias);
        }

输出结果:别名test11

2、加载公私钥。测试签名验签

public static void main(String aa[]) throws Exception {

        FileInputStream is = new FileInputStream(new File("d:\\wymtest.keystore"));

        KeyStore keyStore = KeyStore.getInstance("JKS");
        //这里填设置的keystore密码,两个可以不一致
        keyStore.load(is, "123456".toCharArray());

        //加载别名,这里认为只有一个别名,可以这么取;当有多个别名时,别名要用参数传进来。不然,第二次的会覆盖第一次的
        Enumeration aliasEnum = keyStore.aliases();
        String keyAlias = "" ;
        while (aliasEnum.hasMoreElements()) {
             keyAlias = (String) aliasEnum.nextElement();
            System.out.println("别名"+keyAlias);
        }

        Certificate certificate = keyStore.getCertificate(keyAlias);

        //加载公钥
        PublicKey publicKey = keyStore.getCertificate(keyAlias).getPublicKey();
        //加载私钥,这里填私钥密码
        PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) keyStore.getEntry(keyAlias,
                new KeyStore.PasswordProtection("123456".toCharArray()))).getPrivateKey();

        //加载私钥另一写法
       //PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias, "123456".toCharArray());

        //base64输出私钥
        String strKey = Base64.encodeBase64String(privateKey.getEncoded());
        System.out.println(strKey);

        //测试签名
        String sign = Base64.encodeBase64String(sign("测试msg".getBytes(),privateKey,"SHA1withRSA",null));
        //测试验签
        boolean verfi = verify("测试msg".getBytes(),Base64.decodeBase64(sign), publicKey,"SHA1withRSA",null);
        System.out.println(verfi);

    }

    /**
     * 签名
     */
    public static byte[] sign(byte[] message, PrivateKey privateKey, String algorithm, String provider) throws Exception {
        Signature signature;
        if (null == provider || provider.length() == 0) {
            signature = Signature.getInstance(algorithm);
        } else {
            signature = Signature.getInstance(algorithm, provider);
        }
        signature.initSign(privateKey);
        signature.update(message);
        return signature.sign();
    }
    /**
     * 验签
     */
    public static boolean verify(byte[] message, byte[] signMessage, PublicKey publicKey, String algorithm,
                                 String provider) throws Exception {
        Signature signature;
        if (null == provider || provider.length() == 0) {
            signature = Signature.getInstance(algorithm);
        } else {
            signature = Signature.getInstance(algorithm, provider);
        }
        signature.initVerify(publicKey);
        signature.update(message);
        return signature.verify(signMessage);
    }

最后输出:true。表示加载和测试通过。

3、这个keystore中是单一的密钥对。下面再往里面放一个看看。

keytool -genkey -alias test22 -keyalg RSA -keysize 1024 -keystore d:/wymtest.keystore -validity 4000

再次放一个别名为test22进去。(每次别名都不能相同,否则报错:java.lang.Exception: 没有创建键值对,别名 xxx已经存在
).

此时再用上面1、中的方法测试输入如下:
别名test11
别名test22
所以,keystore中存在多个别名时,应该将别名用参数传递进来。

付:如果使用其他方式,如用openssl之类的工具产生证书和密钥时,别名不是必须的,虽然生产时没有指定,然而却有默认的别名,如1 2 3等。在获取密钥和证书时,依然需要指定别名。
其他命令:https://blog.csdn.net/u014386474/article/details/51996019

你可能感兴趣的:(java)