在java项目中我们经常需要用到加密,比如说密码的加密,关键配置文件的加密,许可证文件的加密,这里我就分享一下我在项目中用到过的加密手段,如果理解错误的地方,还希望能够得到大虾的指点。
在说加密之前,我还要先讲一下BASE64散列算法,很多人认为它也算是一种加密手段,但在我看来BASE64只是一个散列排序,属于一种编码格式,而不能称得上加密手段,只是我们平时使用过程中可以把它拿来用作代码混淆的一种手段。
接下来就是加密,首先加密分单向加密,以及非单向加密,至少我是这么理解的,所谓单向加密就是java中没有提供主流的反破解工具的加密方式,相对的就是非单向加密。
首先单向加密,最大家熟知的可能就是MD5信息摘要算法了,其次就是SHA安全散列算法,还有就是HMAC散列消息鉴别码(自己没有用过)。
首先是MD5,这里文件的MD5加密就不说了,因为本文主要讲解字符串加密。我们的MD5信息摘要算法平时还是挺常用的,因为是jdk自带的一种加密手段,我们可以直接像以下代码这样使用就可以将我们的字符串给加密了。
String bb=DigestUtils.md5Hex(aa);
但是MD5也是有一些它所拥有特点的,就是网络上有提供一些MD5的解密的工具,但是只有比较简单的可以得到免费的解密,比较复杂的都需要支付一些资费,在我的了解里现实中复杂的MD5解码正常个人电脑有时候也不是一两天可以搞定的。所以MD5一般只是用来加密,很少用来解密。
接下来就是SHA安全散列算法,它和MD5有些类似,不可逆,而且它的破解难度比MD5要高的很多,所以从名字既可以看出SHA的安全性相对还是比较高的。
下面就来介绍SHA的使用,首先它目前有五种使用规范(我是这么来理解的哦)吧,SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512,我这里用的是384的。
/**
* SHA散列编码<br/>
* 通过该方法就可以讲文件进行SHA散列排序,这里没有提供SHA散列解码的方法,所有我们提供的包SHA散列是不可逆的。
*
* @param plaintext
* @return
* @throws Exception
*/
public static String encryptSHA(byte[] plaintext) throws Exception {
MessageDigest md = MessageDigest.getInstance(SHA-384);
md.update(plaintext);
return bytes2Hex(md.digest());
}
/**
*
* @param bts
* @return
*/
static String bytes2Hex(byte[] bts) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bts.length; i++) {
sb.append(toHex(bts[i]));
}
return sb.toString();
}
/**
*
* @param buf
* @return
*/
static String toHex(byte buf) {
int n = buf >= 0 ? buf : 256 + buf;
String str = Integer.toHexString(n);
return str.toUpperCase();
}
当然SHA最主要的特性就是安全性,不可逆性,是一种比较常用的加密手段之一。
之后的HMAC我保留意见,如果之后有使用再过来补吧。
接下啦再讲一下非单向加密,出名的不出名的有好多,DES(数据加密算法)、PBE(基于密码验证) 、RSA、DH(密钥一致协议)、DSA(数字签名)、ECC(椭圆曲线密码编码学),而我自己也只用过RSA,废话不都说,先讲一下我使用多的RSA吧。
使用RSA吧,感觉还是挺方便的,没有那么繁琐,唯一感觉不是太好的就是他的解码不是很快,但是正常用还是足够了。下面是它的代码部分:
private static final String KEY_PATH = "C:\\";
public static void main(String[] args) throws Exception {
File savePath = new File(KEY_PATH);
saveKeyPair(generateKeyPair(), savePath);
System.out.println("----------- Key generate success -----------");
}
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
final int KEY_SIZE = 1024;
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGen.genKeyPair();
return keyPair;
}
public static void saveKeyPair(KeyPair keyPair, File savePath) throws IOException {
// Save Pirvate Key
saveObject(keyPair.getPrivate(), new File(savePath, "private.key"));
// Save Public Key
saveObject(keyPair.getPublic(), new File(savePath, "public.key"));
}
private static void saveObject(Object obj, File fileFullName) throws IOException {
FileOutputStream fout = null;
ObjectOutputStream objOut = null;
try {
fout = new FileOutputStream(fileFullName);
objOut = new ObjectOutputStream(fout);
objOut.writeObject(obj);
objOut.flush();
fout.flush();
}
finally {
if (null != objOut) {
objOut.close();
}
if (null != fout) {
fout.close();
}
}
}
public static byte[] encodeRSA(File publicKeyFile, byte[] plaintext) throws Exception {
FileInputStream publicKeyFin = null;
ObjectInputStream pubObjIn = null;
try {
publicKeyFin = new FileInputStream(publicKeyFile);
pubObjIn = new ObjectInputStream(publicKeyFin);
// 获取公钥
RSAPublicKey pbk = (RSAPublicKey) pubObjIn.readObject();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pbk);
return cipher.doFinal(plaintext);
}
finally {
if (null != pubObjIn) {
pubObjIn.close();
}
if (null != publicKeyFin) {
publicKeyFin.close();
}
}
}
public static byte[] decryptRSA(File privateKeyFile, byte[] ciphertext)
throws Exception {
// 获取私钥
FileInputStream privateKeyFin = null;
ObjectInputStream priObjIn = null;
try {
privateKeyFin = new FileInputStream(privateKeyFile);
priObjIn = new ObjectInputStream(privateKeyFin);
RSAPrivateKey prk = (RSAPrivateKey) priObjIn.readObject();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, prk);
return cipher.doFinal(ciphertext);
}
finally {
if (null != priObjIn) {
priObjIn.close();
}
if (null != privateKeyFin) {
privateKeyFin.close();
}
}
}
下面来稍微解释一下RSA的用法吧,使用RSA首先我们需要一对公钥私钥,通过上面的main方法产生一对公钥私钥,然后就可以通过公钥私钥来解密加密了,我这上面的代码主要实现的是公钥加密,私钥解密,代码看的有问题的也可以留言问。
其他非单向加密也没有怎么用,暂时就讲到这里吧,以后有新的再来更新。