package com.fdkankan.sign; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.*; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; public class RsaUtils { static final Base64.Decoder decoder = Base64.getDecoder(); static final Base64.Encoder encoder = Base64.getEncoder(); /** * RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024 */ public static final int KEY_SIZE = 512; public static void main(String[] args) { KeyPairInfo keyPair = getKeyPair(); String publicKey = keyPair.getPublicKey(); String privateKey = keyPair.getPrivateKey(); System.out.println("公钥:"+publicKey); System.out.println("私钥:"+privateKey); String ciphertext = RsaUtils.encipher("123", publicKey); System.out.println(String.format("密文:"+ciphertext)); String deTxt = RsaUtils.decipher(ciphertext, privateKey); System.out.println(deTxt); } /** * 生成公钥、私钥对(keysize=1024) */ public static KeyPairInfo getKeyPair() { return getKeyPair(KEY_SIZE); } /** * 生成公钥、私钥对 * * @param keySize * @return */ public static KeyPairInfo getKeyPair(int keySize) { try { KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(keySize); // 生成一个密钥对,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私钥 RSAPrivateKey oraprivateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公钥 RSAPublicKey orapublicKey = (RSAPublicKey) keyPair.getPublic(); KeyPairInfo pairInfo = new KeyPairInfo(keySize); // 公钥 byte[] publicKeybyte = orapublicKey.getEncoded(); String publicKeyString = encoder.encodeToString(publicKeybyte); pairInfo.setPublicKey(publicKeyString); // 私钥 byte[] privateKeybyte = oraprivateKey.getEncoded(); String privateKeyString = encoder.encodeToString(privateKeybyte); pairInfo.setPrivateKey(privateKeyString); return pairInfo; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取公钥对象 * * @param publicKeyBase64 * @return * @throws InvalidKeySpecException * @throws NoSuchAlgorithmException */ public static PublicKey getPublicKey(String publicKeyBase64) throws InvalidKeySpecException, NoSuchAlgorithmException { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec publicpkcs8KeySpec = new X509EncodedKeySpec(decoder.decode(publicKeyBase64)); PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec); return publicKey; } /** * 获取私钥对象 * * @param privateKeyBase64 * @return * @throws NoSuchAlgorithmException * @throws InvalidKeySpecException */ public static PrivateKey getPrivateKey(String privateKeyBase64) throws NoSuchAlgorithmException, InvalidKeySpecException { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec privatekcs8KeySpec = new PKCS8EncodedKeySpec(decoder.decode(privateKeyBase64)); PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec); return privateKey; } /** * 使用工钥加密 * * @param content 待加密内容 * @param publicKeyBase64 公钥 base64 编码 * @return 经过 base64 编码后的字符串 */ public static String encipher(String content, String publicKeyBase64) { return encipher(content, publicKeyBase64, KEY_SIZE / 8 - 11); } /** * 使用公司钥加密(分段加密) * * @param content 待加密内容 * @param publicKeyBase64 公钥 base64 编码 * @param segmentSize 分段大小,一般小于 keySize/8(段小于等于0时,将不使用分段加密) * @return 经过 base64 编码后的字符串 */ public static String encipher(String content, String publicKeyBase64, int segmentSize) { try { PublicKey publicKey = getPublicKey(publicKeyBase64); return encipher(content, publicKey, segmentSize); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 分段加密 * * @param ciphertext 密文 * @param key 加密秘钥 * @param segmentSize 分段大小,<=0 不分段 * @return */ public static String encipher(String ciphertext, Key key, int segmentSize) { try { // 用公钥加密 byte[] srcBytes = ciphertext.getBytes(); // Cipher负责完成加密或解密工作,基于RSA Cipher cipher = Cipher.getInstance("RSA"); // 根据公钥,对Cipher对象进行初始化 cipher.init(Cipher.ENCRYPT_MODE, key); byte[] resultBytes = null; if (segmentSize > 0) resultBytes = cipherDoFinal(cipher, srcBytes, segmentSize); // 分段加密 else resultBytes = cipher.doFinal(srcBytes); String base64Str = Base64.getEncoder().encodeToString(resultBytes); return base64Str; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 分段大小 * * @param cipher * @param srcBytes * @param segmentSize * @return * @throws IllegalBlockSizeException * @throws BadPaddingException * @throws IOException */ public static byte[] cipherDoFinal(Cipher cipher, byte[] srcBytes, int segmentSize) throws IllegalBlockSizeException, BadPaddingException, IOException { if (segmentSize <= 0) throw new RuntimeException("分段大小必须大于0"); ByteArrayOutputStream out = new ByteArrayOutputStream(); int inputLen = srcBytes.length; int offSet = 0; byte[] cache; int i = 0; // 对数据分段解密 while (inputLen - offSet > 0) { if (inputLen - offSet > segmentSize) { cache = cipher.doFinal(srcBytes, offSet, segmentSize); } else { cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet); } out.write(cache, 0, cache.length); i++; offSet = i * segmentSize; } byte[] data = out.toByteArray(); out.close(); return data; } /** * 使用私钥解密 * * @param contentBase64 待加密内容,base64 编码 * @param privateKeyBase64 私钥 base64 编码 * @return * @segmentSize 分段大小 */ public static String decipher(String contentBase64, String privateKeyBase64) { return decipher(contentBase64, privateKeyBase64, KEY_SIZE / 8); } /** * 使用私钥解密(分段解密) * * @param contentBase64 待加密内容,base64 编码 * @param privateKeyBase64 私钥 base64 编码 * @return * @segmentSize 分段大小 */ public static String decipher(String contentBase64, String privateKeyBase64, int segmentSize) { try { PrivateKey privateKey = getPrivateKey(privateKeyBase64); return decipher(contentBase64, privateKey, segmentSize); } catch (Exception e) { e.printStackTrace(); return null; } } /** * 分段解密 * * @param contentBase64 密文 * @param key 解密秘钥 * @param segmentSize 分段大小(小于等于0不分段) * @return */ public static String decipher(String contentBase64, Key key, int segmentSize) { try { // 用私钥解密 byte[] srcBytes = Base64.getDecoder().decode(contentBase64); // Cipher负责完成加密或解密工作,基于RSA Cipher deCipher = Cipher.getInstance("RSA"); // 根据公钥,对Cipher对象进行初始化 deCipher.init(Cipher.DECRYPT_MODE, key); byte[] decBytes = null;// deCipher.doFinal(srcBytes); if (segmentSize > 0) decBytes = cipherDoFinal(deCipher, srcBytes, segmentSize); // 分段加密 else decBytes = deCipher.doFinal(srcBytes); String decrytStr = new String(decBytes); return decrytStr; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 秘钥对 */ public static class KeyPairInfo { String privateKey; String publicKey; int keySize = 0; public KeyPairInfo(int keySize) { setKeySize(keySize); } public KeyPairInfo(String publicKey, String privateKey) { setPrivateKey(privateKey); setPublicKey(publicKey); } public String getPrivateKey() { return privateKey; } public void setPrivateKey(String privateKey) { this.privateKey = privateKey; } public String getPublicKey() { return publicKey; } public void setPublicKey(String publicKey) { this.publicKey = publicKey; } public int getKeySize() { return keySize; } public void setKeySize(int keySize) { this.keySize = keySize; } } }