welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ:9167702333 邮箱:admin@xlongwei.com

RSAUtil非对称加密解密工具


分类 Java   关键字 分享   标签 java   algorithm   发布 hongwei  1430904044242
注意 转载须保留原文链接,译文链接,作者译者等信息。  
RSAUtil非对称加密解密工具,RSA算法和公钥都是公开的,保管好私钥就能保证安全(破解极为困难)。
  • getKeyPair+getKeyString,支持生成密钥对和导出字符串以便保存,密钥长度最好512位以上(要整除8因为加密较长数据时需分块执行,且密文长度等于密钥长度),
  • getPrivateKey+getPublicKey,支持从字符串加载密钥,支持从证书加载密钥
  • sign+verify,支持签名和校验,签名可以防止数据被非法篡改(任何数据改动都会导致校验失败)
  • encrypt+decrypt,加密和解密,算法RSA/None/PKCS1Padding每次加密的密文都不同(填充随机数,提高了安全性),算法RSA/None/NoPadding在相同条件下产生相同密文,非对称加密相比对称加密要慢很多,所以通常不用RSA加密太多数据,而是加密对称加密的密码,然后对称加密敏感数据
public class RSAUtil {
private static String keyStoreType = "PKCS12";
private static String certificateFactoryAlgorithm = "X.509";
private static String rsa = "RSA";
private static String rsaSign = "SHA1withRSA";//MD5WITHRSA SHA512withRSA
private static String rsaCipher = "RSA/None/PKCS1Padding";//RSA/None/NoPadding重复密文 RSA/None/PKCS1Padding不重复密文(有随机数填充)
private static int keySize = 1024;//2048 为提高保密强度要求512以上(SunJCE要整除8),建议对称加密数据+RSA加密密码,RSA比较慢

private static boolean bouncyCastleProviderAvailable = false;
private static String classBouncyCastleProvider = "org.bouncycastle.jce.provider.BouncyCastleProvider";
private static Logger logger = LoggerFactory.getLogger(RSAUtil.class);

static {
try {
Class<?> clazz = Class.forName(classBouncyCastleProvider);
Provider bouncyCastleProvider = (Provider)clazz.newInstance();
Security.addProvider(bouncyCastleProvider);
bouncyCastleProviderAvailable = true;
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
logger.warn("fail to Security.addProvider(BC): "+e.getMessage(), e);
}
}

/**
* 读取私钥证书
*/
public static PrivateKey getPrivateKey(InputStream is, String pwd) {
try {
KeyStore ks = KeyStore.getInstance(keyStoreType);
char[] ps = pwd!=null ? pwd.toCharArray() : null;
ks.load(is, ps);
Enumeration<String> as = ks.aliases();
return (PrivateKey)ks.getKey(as.hasMoreElements() ? as.nextElement() : null, ps);
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | UnrecoverableKeyException e) {
logger.warn("fail to getPrivateKey from InputStream is: "+e.getMessage(), e);
} finally {
IOUtils.closeQuietly(is);
}
return null;
}

/**
* 读取公钥证书
*/
public static PublicKey getPublicKey(InputStream is) {
try {
CertificateFactory cf = CertificateFactory.getInstance(certificateFactoryAlgorithm);
Certificate c = cf.generateCertificate(is);
return c.getPublicKey();
} catch (CertificateException e) {
logger.warn("fail to getPublicKey from InputStream is: "+e.getMessage(), e);
} finally {
IOUtils.closeQuietly(is);
}
return null;
}

/**
* 加载私钥串
*/
public static PrivateKey getPrivateKey(String privateKey) {
try {
byte[] bs = Base64.decodeBase64(privateKey);
EncodedKeySpec eks = new PKCS8EncodedKeySpec(bs);
KeyFactory kf = KeyFactory.getInstance(rsa);
return kf.generatePrivate(eks);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
logger.warn("fail to getPrivateKey from String privateKey: "+e.getMessage(), e);
}
return null;
}

/**
* 加载公钥串
*/
public static PublicKey getPublicKey(String publicKey) {
try {
byte[] bs = Base64.decodeBase64(publicKey);
KeyFactory kf = KeyFactory.getInstance(rsa);
EncodedKeySpec eks = new X509EncodedKeySpec(bs);
return kf.generatePublic(eks);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
logger.warn("fail to getPublicKey from String publicKey: "+e.getMessage(), e);
}
return null;
}

/**
* 公钥私钥转字符串
*/
public static String getKeyString(Key key) {
byte[] bs = key.getEncoded();
return Base64.encodeBase64String(bs);
}

/**
* 生成非对称密钥对
*/
public static KeyPair getKeyPair() {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(rsa);
kpg.initialize(keySize);
return kpg.generateKeyPair();
} catch (NoSuchAlgorithmException e) {
logger.warn("fail to getKeyPair: "+e.getMessage(), e);
}
return null;
}

/**
* 私钥签名
*/
public static String sign(PrivateKey privateKey, String data) {
try {
Signature s = Signature.getInstance(rsaSign);
s.initSign(privateKey);
s.update(data.getBytes(Charsets.UTF_8));
return Base64.encodeBase64String(s.sign());
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
return null;
}

/**
* 公钥校验签名
*/
public static boolean verify(PublicKey publicKey, String data, String signature) {
try {
Signature s = Signature.getInstance(rsaSign);
s.initVerify(publicKey);
s.update(data.getBytes(Charsets.UTF_8));
return s.verify(Base64.decodeBase64(signature));
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
e.printStackTrace();
}
return false;
}

/**
* 公钥加密数据
*/
public static String encrypt(PublicKey publicKey, String data) {
try {
Cipher c = bouncyCastleProviderAvailable ? Cipher.getInstance(rsaCipher, "BC") : Cipher.getInstance(rsaCipher);
c.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] bs = data.getBytes(Charsets.UTF_8);
int bufferSize = keySize/8 - 11;//1024限制117字节 2048限制245字节
byte[] buffer = new byte[bufferSize];
int position = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
do {
int read = Math.min(bufferSize, bs.length-position);
System.arraycopy(bs, position, buffer, 0, read);
c.update(buffer, 0, read);
byte[] cs = c.doFinal();//加密结果全是256字节
baos.write(cs);
position+=read;
}while(position<bs.length);
byte[] bss = baos.toByteArray();
return Base64.encodeBase64String(bss);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException | IOException e) {
e.printStackTrace();
}
return null;
}

/**
* 私钥解密数据
*/
public static String decrypt(PrivateKey privateKey, String data) {
try {
Cipher c = bouncyCastleProviderAvailable ? Cipher.getInstance(rsaCipher, "BC") : Cipher.getInstance(rsaCipher);
c.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bs = Base64.decodeBase64(data);
int bufferSize = keySize/8;//密文长度等于密钥长度
byte[] buffer = new byte[bufferSize];
int position = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
do {
int read = Math.min(bufferSize, bs.length-position);
System.arraycopy(bs, position, buffer, 0, read);
c.update(buffer, 0, read);
byte[] cs = c.doFinal();
baos.write(cs);
position+=read;
}while(position<bs.length);
byte[] bss = baos.toByteArray();
return StringUtils.newStringUtf8(bss);
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchProviderException | IOException e) {
e.printStackTrace();
}
return null;
}
//列出所有的Service和Provider信息
public static void main(String[] args) {
List<Service> services = new ArrayList<>();
Provider[] providers = Security.getProviders();
for(Provider provider : providers) {
// if(provider.getName().equals("BC"))
services.addAll(provider.getServices());
}
Collections.sort(services, new Comparator<Service>() {
public int compare(Service o1, Service o2) {
int type = o1.getType().compareTo(o2.getType());
if(type!=0) return type;
int algorithm = o1.getAlgorithm().compareTo(o2.getAlgorithm());
if(algorithm!=0) return algorithm;
return o1.getProvider().getName().compareTo(o2.getProvider().getName());
}
});
for(Service service : services) {
try {
Field field = Service.class.getDeclaredField("aliases");
field.setAccessible(true);
@SuppressWarnings("unchecked")
List<String> aliases = (List<String>)field.get(service);
System.out.println(service.getType()+"\t"+service.getAlgorithm()+"\t"+service.getProvider().getName()+"\t"+service.getClassName()+"\t"+(org.apache.commons.lang3.StringUtils.join(aliases, ",")));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

security.xls