JAVA RSA 私钥签名 公钥验证签名 公钥验签
1.待签名字符串转为byte数组时,一般使用UTF8。
2.将私钥字符串(PKCS8格式)转为PKCS8EncodedKeySpec对象。
3.使用Signature对象的 update+sign 方法算出签名值,结果为byte数组。
4.签名值是byte数组,不便于传输,一般是转为BASE64字符串来传输。
5.公钥字符串转为X509EncodedKeySpec对象,Signature.update+Signature.verify 验证签名。
6.openssl生成的私钥默认是PKCS1的,示例中是转成了PKCS8格式。
7.使用了commons-codec这个JAR包来转换base64字符串。
8.如果要和其它语言互通,需要协商好:待签名字符串转为byte数组的编码、签名值byte数组转字符串的编码、哈希算法(SHA1WithRSA 还是 SHA256WithRSA)。
示例私钥,PKCS8格式:
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDyNsCen1C5SKAy2qg7CUJRtrqgcP3f4eTv0oHcV7LIj3vj5oy+0SVk4USsKOSW+Ddg+Bn12bmBwxCA1aMcoSBzeLQFQT4OLA87I1+EP+b2Lrqf4xfU/77e+bY0MU6yatyb9rf99P5mDIn88JL89Z1rJYQrZnwJP1f8EAL0JcGY5bXO9+aYtDBP3qL7dDmuk+Wfc/57q233Lzr3zBCQ5EH3XuTgEr6b3IVduf4f/mrHWDvEldNLlj+xTjKnSZgR16yNYevaRLVsOzlIN+0ggUqeU+ZQDf9XnJEkd9yBbLfWnjOgGa4VZ5Y7nurEnBaOD3IG/vGfSZUEKtdw3uxbD+PZAgMBAAECggEBALdZrxHkM60uRuZ4EuUtqyBEHJ4bKnLxguXwChGL6XBc/UGVYnGHzLDCvcM86V1G5FTpOm2atQx/Zty/28tuRSxj8JIRwzHjNFxl+IYaAXHWCbvComXAevI7QSvdL19r+Teu2bTKYlFJqKLqUbpfCxzyt0xLNhWh9659SF8cvaJIuAblrKziXAyFYPDcLdmDPJI2rlsKKPiO5yXxOaj70pmULFBi4sKemabu23HtJkg48SdCcE4eZQhfIvloSDv4HYNT3l6sLezrHCemBIeTRk5V3wB96A/rjR1PgUIXttl6rUDp4nfMopTZpXnD7zPXhw5is7d/aiHc+E6CQvCqvQECgYEA+yADM23b53LNJs4shZHqC+Dc35j5DJjNswP0XA2Aq0SypY0fkUjI4qjiS2y4ktNwiFc9ljFOVyfQIczKcNXuhFswvbannBqqg7VYOCD4175URirfgtM4xU4TQiHm+5jyTz3GQiF7PdN2ISKGTiLs/fXrw3utaSgc7dukCYs6ZxECgYEA9up0gDZQ3/YhIjuEQBHiHhRQ9X3PriD8J4DJqTYSDG1OBZFPfO3YocJkCMTq9c2Jl2qPbLVP1BveAjIR6aExwQuolwisoM+QGurIcZY2m5dklYitRVg6+9AitCU/cqZK9U0vAPuDb3x1ZR/0+rYhQGcY+DFchtapTqzHSfXggEkCgYEA0PyXLVmjxD2Z1U2HZ7FC4ZfEuKAJwx33MZ984I6sIdwOABAt0S6NX3PEv5g/EpG7+PsBWdi2pXmQkFBpuPWQhb2OFpPHcPYQKYPlYvCtpn3SjIJpd+poOGr9Q/AK1h82qBN0xtwuQAmXKYQd2TDfoYnjJs/qRLUJPjmnjfm8JMECgYEAttoXnl8a81AdZ3F11dCoiCf5cGNUKhqJQWPRc3r0ULmdfugGWnj05Y3EcO4LJi6pBzXFsvZugKCGf0+/DinuY4yTtA2bcZdkm1plSCC6ney2czp9Po5BV/vhx1CSNQBLIG+hMHQR+LzNXy8UR5oa88ulpR9A6yYKyZWQHAh20ekCgYEAvgXQSX0GiXTMTTWUWtcrvHkATb3KKENcH8jmwa6sw/jU4FP2IxUmRwxRr/1mQ1RB/5RSYH/wbIfvoytBEVj40DMJzn0Aq/0+EwU3DP8ej6vkIK/U1/uxz/bVr7R7+dI2uw0THqXLo4hHTFElBZTREbnuWcqDPL+6ZU7FvpHP4iM=
公钥:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8jbAnp9QuUigMtqoOwlCUba6oHD93+Hk79KB3FeyyI974+aMvtElZOFErCjklvg3YPgZ9dm5gcMQgNWjHKEgc3i0BUE+DiwPOyNfhD/m9i66n+MX1P++3vm2NDFOsmrcm/a3/fT+ZgyJ/PCS/PWdayWEK2Z8CT9X/BAC9CXBmOW1zvfmmLQwT96i+3Q5rpPln3P+e6tt9y8698wQkORB917k4BK+m9yFXbn+H/5qx1g7xJXTS5Y/sU4yp0mYEdesjWHr2kS1bDs5SDftIIFKnlPmUA3/V5yRJHfcgWy31p4zoBmuFWeWO57qxJwWjg9yBv7xn0mVBCrXcN7sWw/j2QIDAQAB
待签名字符串:
Hello中国
工具类:
package com.company; import org.apache.commons.codec.binary.Base64; import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; public class RsaUtil { /** * 签名 * @param preStr 待签名字符串 * @param privateKeyPKCS8 私钥字符串PKCS8格式 * @return base64字符串 * @throws Exception */ public static String getSign(String preStr, String privateKeyPKCS8) throws Exception { privateKeyPKCS8 = privateKeyPKCS8.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replace("\r", "").replace("\n", "").trim(); String strSign = ""; String suite = "SHA256WithRSA"; //初始化算法SHA256 Signature signature = Signature.getInstance(suite); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyPKCS8)); //初始化私钥+RSA KeyFactory keyFac = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFac.generatePrivate(keySpec); signature.initSign(privateKey); //待签名字符串转byte数组使用UTF8 byte[] msgBuf = preStr.getBytes("UTF8"); signature.update(msgBuf); byte[] byteSign = signature.sign(); //签名值byte数组转字符串用BASE64 strSign = Base64.encodeBase64String(byteSign); return strSign; } /** * 验证签名 * @param preStr 待验证签名字符串 * @param publicKeyStr 公钥字符串 * @param rspSign 待验证签名值 * @return 是否 * @throws Exception */ public static boolean verifySign(String preStr, String publicKeyStr, String rspSign) throws Exception { publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "").replace("\r", "").replace("\n", "").trim(); //待验证签名值base64解码 byte[] sign = Base64.decodeBase64(rspSign); String suite = "SHA256WithRSA"; //初始化算法SHA256 Signature signature = Signature.getInstance(suite); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr)); //初始化公钥+RSA KeyFactory keyFac = KeyFactory.getInstance("RSA"); PublicKey pubKey = keyFac.generatePublic(keySpec); signature.initVerify(pubKey); //待签名字符串转byte数组使用UTF8 byte[] msgBuf = preStr.getBytes("UTF8"); signature.update(msgBuf); boolean bRst = signature.verify(sign); return bRst; } }
调用DEMO:
package com.company; public class Main { public static void main(String[] args) { String privateKeyPKCS8 = "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDyNsCen1C5SKAy2qg7CUJRtrqgcP3f4eTv0oHcV7LIj3vj5oy+0SVk4USsKOSW+Ddg+Bn12bmBwxCA1aMcoSBzeLQFQT4OLA87I1+EP+b2Lrqf4xfU/77e+bY0MU6yatyb9rf99P5mDIn88JL89Z1rJYQrZnwJP1f8EAL0JcGY5bXO9+aYtDBP3qL7dDmuk+Wfc/57q233Lzr3zBCQ5EH3XuTgEr6b3IVduf4f/mrHWDvEldNLlj+xTjKnSZgR16yNYevaRLVsOzlIN+0ggUqeU+ZQDf9XnJEkd9yBbLfWnjOgGa4VZ5Y7nurEnBaOD3IG/vGfSZUEKtdw3uxbD+PZAgMBAAECggEBALdZrxHkM60uRuZ4EuUtqyBEHJ4bKnLxguXwChGL6XBc/UGVYnGHzLDCvcM86V1G5FTpOm2atQx/Zty/28tuRSxj8JIRwzHjNFxl+IYaAXHWCbvComXAevI7QSvdL19r+Teu2bTKYlFJqKLqUbpfCxzyt0xLNhWh9659SF8cvaJIuAblrKziXAyFYPDcLdmDPJI2rlsKKPiO5yXxOaj70pmULFBi4sKemabu23HtJkg48SdCcE4eZQhfIvloSDv4HYNT3l6sLezrHCemBIeTRk5V3wB96A/rjR1PgUIXttl6rUDp4nfMopTZpXnD7zPXhw5is7d/aiHc+E6CQvCqvQECgYEA+yADM23b53LNJs4shZHqC+Dc35j5DJjNswP0XA2Aq0SypY0fkUjI4qjiS2y4ktNwiFc9ljFOVyfQIczKcNXuhFswvbannBqqg7VYOCD4175URirfgtM4xU4TQiHm+5jyTz3GQiF7PdN2ISKGTiLs/fXrw3utaSgc7dukCYs6ZxECgYEA9up0gDZQ3/YhIjuEQBHiHhRQ9X3PriD8J4DJqTYSDG1OBZFPfO3YocJkCMTq9c2Jl2qPbLVP1BveAjIR6aExwQuolwisoM+QGurIcZY2m5dklYitRVg6+9AitCU/cqZK9U0vAPuDb3x1ZR/0+rYhQGcY+DFchtapTqzHSfXggEkCgYEA0PyXLVmjxD2Z1U2HZ7FC4ZfEuKAJwx33MZ984I6sIdwOABAt0S6NX3PEv5g/EpG7+PsBWdi2pXmQkFBpuPWQhb2OFpPHcPYQKYPlYvCtpn3SjIJpd+poOGr9Q/AK1h82qBN0xtwuQAmXKYQd2TDfoYnjJs/qRLUJPjmnjfm8JMECgYEAttoXnl8a81AdZ3F11dCoiCf5cGNUKhqJQWPRc3r0ULmdfugGWnj05Y3EcO4LJi6pBzXFsvZugKCGf0+/DinuY4yTtA2bcZdkm1plSCC6ney2czp9Po5BV/vhx1CSNQBLIG+hMHQR+LzNXy8UR5oa88ulpR9A6yYKyZWQHAh20ekCgYEAvgXQSX0GiXTMTTWUWtcrvHkATb3KKENcH8jmwa6sw/jU4FP2IxUmRwxRr/1mQ1RB/5RSYH/wbIfvoytBEVj40DMJzn0Aq/0+EwU3DP8ej6vkIK/U1/uxz/bVr7R7+dI2uw0THqXLo4hHTFElBZTREbnuWcqDPL+6ZU7FvpHP4iM="; String preStr = "Hello中国"; String publicKeyStr="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8jbAnp9QuUigMtqoOwlCUba6oHD93+Hk79KB3FeyyI974+aMvtElZOFErCjklvg3YPgZ9dm5gcMQgNWjHKEgc3i0BUE+DiwPOyNfhD/m9i66n+MX1P++3vm2NDFOsmrcm/a3/fT+ZgyJ/PCS/PWdayWEK2Z8CT9X/BAC9CXBmOW1zvfmmLQwT96i+3Q5rpPln3P+e6tt9y8698wQkORB917k4BK+m9yFXbn+H/5qx1g7xJXTS5Y/sU4yp0mYEdesjWHr2kS1bDs5SDftIIFKnlPmUA3/V5yRJHfcgWy31p4zoBmuFWeWO57qxJwWjg9yBv7xn0mVBCrXcN7sWw/j2QIDAQAB"; try { String sign = RsaUtil.getSign(preStr, privateKeyPKCS8); System.out.println("签名为:" + sign); boolean bRst=RsaUtil.verifySign(preStr, publicKeyStr,sign); System.out.println("验证签名结果:" + bRst); } catch (Exception ex) { System.out.println(ex.getMessage()); } } }
-源码:https://gitee.com/runliuv/mypub/tree/master/javaproj/java%E7%A7%81%E9%92%A5%E7%AD%BE%E5%90%8D%E5%85%AC%E9%92%A5%E9%AA%8C%E7%AD%BE
IDEA 社区版打开。