签名与确认签名 RSA算法

╄→гoц情女王★ 提交于 2020-01-20 20:52:42

1.使用RSA算法生成密钥对

    /**
     *  生成RSA随机密钥对(公钥和私钥)
     * @return
     */
    public static Map<String, String> createKeyPair() throws Exception {
        Map<String,String> keyPairMap = new HashMap<>();
        // 密钥生成器,基于RSA算法
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥生成器,密钥大小为96-1024位
        keyPairGenerator.initialize(1024, SecureRandom.getInstance("SHA1PRNG"));
        // 生成一个密钥对,保存在KeyPair中
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        // 获取公钥及公钥字节数组
        PublicKey publicKey = keyPair.getPublic();
        byte[] publicKeyBytes = publicKey.getEncoded();
        // 获取私钥及私钥字节数组
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] privateKeyBytes = privateKey.getEncoded();
        // 转换成16进制字符保存在map中
        keyPairMap.put(PUBLIC_KEY, byte2Hex(publicKeyBytes));
        keyPairMap.put(PRIVATE_KEY, byte2Hex(privateKeyBytes));
        return keyPairMap;
    }

2.使用私钥签名

    /**
     *  使用私钥(RSA算法生成)对数据(一般是数字摘要)进行签名
     * @param contents
     * @param privateKeyString
     * @return
     */
    public static String sign(String contents, String privateKeyString) throws Exception {
        if (contents != null && privateKeyString != null && !"".equals(contents) && !"".equals(privateKeyString)) {
            // 获取私钥
            PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(hex2Byte(privateKeyString)));
            // 实例化一个用SHA算法进行散列,用RSA算法进行加密的Signature
            Signature signature = Signature.getInstance("SHA1withRSA");
            // 加载加密散列码用的私钥
            signature.initSign(privateKey);
            // 进行散列,对产生的散列码进行加密并返回
            signature.update(contents.getBytes("UTF-8"));
            // 进行签名
            byte[] signBytes = signature.sign();
            return byte2Hex(signBytes);
        }
        return null;
    }

3.使用公钥确认签名

    /**
     *  使用公钥对签名数据进行验证
     * @param contents
     * @param signString
     * @param publicKeyString
     * @return
     */
    public static boolean checkSign(String contents, String signString, String publicKeyString) throws Exception {
        if (contents == null || signString == null || publicKeyString == null) {
            return false;
        }
        // 获取公钥
        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(hex2Byte(publicKeyString)));
        // 实例化一个用SHA算法进行散列,用RSA算法进行加密的Signature
        Signature signature = Signature.getInstance("SHA1withRSA");
        // 加载公钥
        signature.initVerify(publicKey);
        // 更新原数据
        signature.update(contents.getBytes("UTF-8"));
        // 返回签名是否正确
        return signature.verify(hex2Byte(signString));
    }

--------------------------------------

工具方法

    /**
     *  将byte[]数组转换成16进制字符。一个byte生成两个字符,长度对应1:2
     * @param bytes,输入byte[]数组
     * @return 16进制字符
     */
    public static String byte2Hex(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        // 遍历byte[]数组,将每个byte数字转换成16进制字符,再拼接起来成字符串
        for (int i = 0; i < bytes.length; i++) {
            // 每个byte转换成16进制字符时,bytes[i] & 0xff如果高位是0,输出将会去掉,所以+0x100(在更高位加1),再截取后两位字符
            builder.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
        }
        return builder.toString();
    }

    /**
     *  将16进制字符转换成byte[]数组。与byte2Hex功能相反。
     * @param string 16进制字符串
     * @return byte[]数组
     */
    public static byte[] hex2Byte(String string) {
        if (string == null || string.length() < 1) {
            return null;
        }
        // 因为一个byte生成两个字符,长度对应1:2,所以byte[]数组长度是字符串长度一半
        byte[] bytes = new byte[string.length() / 2];
        // 遍历byte[]数组,遍历次数是字符串长度一半
        for (int i = 0; i < string.length() / 2; i++) {
            // 截取没两个字符的前一个,将其转为int数值
            int high = Integer.parseInt(string.substring(i * 2, i * 2 + 1), 16);
            // 截取没两个字符的后一个,将其转为int数值
            int low = Integer.parseInt(string.substring(i * 2 + 1, i * 2 + 2), 16);
            // 高位字符对应的int值*16+低位的int值,强转成byte数值即可
            // 如dd,高位13*16+低位13=221(强转成byte二进制11011101,对应十进制-35)
            bytes[i] = (byte) (high * 16 + low);
        }
        return bytes;
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!