項目有個需求,使用私鑰簽名請求body內容,放在請求頭部,作為頭部一個字段內容請求外部服務,簽名有二種方式,對方提供私鑰串/直接提供pfx私鑰文件。
一. 提供私鑰串 示例代碼如下:
public static void main(String[] args) { String key2 = "MII***==" //使用自己的私鑰替換 try { byte[] data = "test".getBytes("UTF8"); Signature sig = Signature.getInstance("MD5withRSA");//SHA1WithRSA 簽名算法 sig.initSign(readRSAPrivateKey(key2)); sig.update(data); byte[] signatureBytes = sig.sign(); System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes)); } catch (Exception e) { e.printStackTrace(); } } public static String signContent(String content) throws Exception{ byte[] data = content.getBytes("UTF8"); Signature sig = Signature.getInstance("MD5withRSA"); sig.initSign(readRSAPrivateKey(key2)); sig.update(data); byte[] signatureBytes = sig.sign(); return new String(java.util.Base64.getEncoder().encode(signatureBytes)); //new BASE64Encoder().encode(signatureBytes);
}
public static PrivateKey readRSAPrivateKey(String privateKey) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { byte[] keyBytes = java.util.Base64.getDecoder().decode(privateKey.getBytes());
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey key = kf.generatePrivate(spec);
return key; }
如果需要公鑰解碼,結合私鑰簽名,代碼如下
import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.Signature; import sun.misc.BASE64Encoder; public class MainClass { public static void main(String[] args) throws Exception { KeyPair keyPair = getKeyPair(); byte[] data = "test".getBytes("UTF8"); Signature sig = Signature.getInstance("SHA1WithRSA"); sig.initSign(keyPair.getPrivate()); sig.update(data); byte[] signatureBytes = sig.sign(); System.out.println("Signature:" + new BASE64Encoder().encode(signatureBytes)); sig.initVerify(keyPair.getPublic()); sig.update(data); System.out.println(sig.verify(signatureBytes)); } private static KeyPair getKeyPair() throws NoSuchAlgorithmException { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(1024); return kpg.genKeyPair(); } }
二. 如果別人提供給你的是pfx文件,你可以選擇把peivate key提取出來,或者直接使用pfx文件簽名也可以。
1. 提取的命令:openssl pkcs12 -in test-private.pfx -nocerts -nodes -out key2.pem
如果需要的是老格式的:openssl pkcs8 -in key.pem -out rsakey.pem
2. 直接使用pfx文件簽名String代碼如下
/** * @param algorithm 簽名算法: SHA1WithRSA / MD5withRSA等 * @param password 密碼 * @param privateKeyPath pfx文件路徑 * @throws Exception */ public RSASignUtils(String algorithm, String password, String privateKeyPath) throws Exception { this.algorithm = algorithm; this.password = password; try{ KeyStore ks = KeyStore.getInstance("PKCS12"); InputStream fis = RSASignUtils.class.getResourceAsStream(privateKeyPath); char[] nPassword = null; if ((password == null) || password.trim().equals("")) { nPassword = null; } else { nPassword = password.toCharArray(); } ks.load(fis, nPassword); fis.close(); Enumeration enuml = ks.aliases(); String keyAlias = null; if (enuml.hasMoreElements()) { keyAlias = (String) enuml.nextElement(); logger.info("RSASignUtils alias=[" + keyAlias + "]"); } logger.info("RSASignUtils is key entry = " + ks.isKeyEntry(keyAlias)); PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword); logger.info("RSASignUtils keystore type = " + ks.getType()); signature = Signature.getInstance(algorithm); signature.initSign(prikey); } catch (Exception e) { logger.error(String.format("RSA signature object generate failure...%s", e.getMessage())); throw e; } } public String generate(String body) throws UnsupportedEncodingException, SignatureException { //Read the string into a buffer byte[] dataInBytes = body.getBytes("UTF-8"); //update signature with data to be signed signature.update(dataInBytes); //sign the data byte[] signedInfo = signature.sign(); return Base64.getEncoder().encodeToString(signedInfo);//Base64.encode(signedInfo); }