openssl JAVA 签名方法

2019-08-19  本文已影响0人  chuan_bai

1.私钥不能直接被java使用(但可以被openssl使用),需要进行PKCS#8编码

openssl pkcs8 -topk8 -in rsa_private_key.pem -out pkcs8_rsa_private_key.pem -nocrypt

2.签名方法

    /**
     * rsa签名
     *
     * @param content    待签名的字符串
     * @param privateKey rsa私钥字符串
     * @param charset    字符编码
     * @return 签名结果
     * @throws Exception 签名失败则抛出异常
     */
    public String rsaSign(String content, String privateKey, String charset) throws SignatureException {
        try {

            PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", new ByteArrayInputStream(privateKey.getBytes()));

            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(priKey);
            if (StringUtils.isEmpty(charset)) {
                signature.update(content.getBytes());
            } else {
                signature.update(content.getBytes(charset));
            }

            byte[] signed = signature.sign();
            return new String(Base64.encodeBase64(signed));
        } catch (Exception e) {
            throw new SignatureException("RSAcontent = " + content + "; charset = " + charset, e);
        }
    }


    public PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
        if (ins == null || StringUtils.isEmpty(algorithm)) {
            return null;
        }

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        byte[] encodedKey = StreamUtil.readText(ins).getBytes();
        encodedKey = Base64.decodeBase64(encodedKey);
        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
    }

    /**
     * rsa验签
     *
     * @param content 被签名的内容
     * @param sign 签名后的结果
     * @param publicKey rsa公钥
     * @param charset 字符集
     * @return 验签结果
     * @throws SignatureException 验签失败,则抛异常
     */
    boolean doCheck(String content, String sign, String publicKey, String charset) throws SignatureException {
        try {
            PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));

            Signature signature = Signature.getInstance("SHA1WithRSA");
            signature.initVerify(pubKey);
            signature.update(getContentBytes(content, charset));
            return signature.verify(Base64.decodeBase64(sign.getBytes()));
        } catch (Exception e) {
            throw new SignatureException("RSA验证签名[content = " + content + "; charset = " + charset
                    + "; signature = " + sign + "]发生异常!", e);
        }
    }

    private PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws NoSuchAlgorithmException {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

            StringWriter writer = new StringWriter();
            StreamUtil.io(new InputStreamReader(ins), writer);
            byte[] encodedKey = writer.toString().getBytes();

            // 先base64解码
            encodedKey = Base64.decodeBase64(encodedKey);
            return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
        } catch (IOException ex) {
            // 不可能发生
        } catch (InvalidKeySpecException ex) {
            // 不可能发生
        }
        return null;
    }

    private byte[] getContentBytes(String content, String charset) throws UnsupportedEncodingException {
        if (StringUtil.isEmpty(charset)) {
            return content.getBytes();
        }

        return content.getBytes(charset);
    }

3.测试方法

    public static void main(String[] args) throws SignatureException {
        String content = "content";
        RasSign rasSign = new RasSign();
        String signResult = rasSign.rsaSign(content, "key", "UTF-8");
        System.out.println("signResult:" +signResult);
    }
上一篇下一篇

猜你喜欢

热点阅读