简介
常见的加密算法可分为三大类:对称加密,非对称加密和hash算法
对称加密:加密和解密使用相同的密钥。
DES、3DES、AES、Blowfish、IDEA、DESX、RC-4、RC-5、RC-6
非对成加密:加密和解密使用不同的密钥
RSA、ECC、DSA
hash算法:通过算法将值映射到表中一个位置来訪问记录,以加快查找的速度。的主要适用于空间换时间
MD5、HMAC、SHA、SHA-1、MD2、MD4、HMAC-MD5、HMAC-SHA1
具体的算法java实现
详细的加密可参考SecretKeyFactory 加密过程中由于加密算结果方便展示这里采用base64进行编码
hash算法详细可参考MessageDigest
对称加密
DES、3DES
public static byte[] encrypt(byte[] datasource, String password) throws Exception {
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(password.getBytes());
//创建一个密钥工厂,然后用它把DESKeySpec转换成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
//cipher对象世纪完成加密操作
Cipher cipher = Cipher.getInstance("DES");
//用密钥初始化cipher对象
cipher.init(cipher.ENCRYPT_MODE, securekey, random);
//现在,获取数据并加密
//正式执行加密操作
byte[] r = cipher.doFinal(datasource);
return encoder.encode(r);
}
public static byte[] decrypt(byte[] src, String password) throws Exception {
src = decoder.decode(src);
//DES算法要求有一个可信任的随即数源
SecureRandom random = new SecureRandom();
DESKeySpec deskey = new DESKeySpec(password.getBytes("utf-8"));
//创建一个密钥工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//将DESKeySpec对象转换成secretKey对象
SecretKey secretKey = keyFactory.generateSecret(deskey);
//cipher对象世纪完成解密操作
Cipher cipher = Cipher.getInstance("DES");
cipher.init(cipher.DECRYPT_MODE, secretKey, random);
return cipher.doFinal(src);
}
static final Base64.Decoder decoder = Base64.getDecoder();
static final Base64.Encoder encoder = Base64.getEncoder();
public static void main(String[] args) throws Exception {
String str = "代价密数据";
//长度是8的倍数
String password = "1234567887654321";
byte[] result = DES.encrypt(str.getBytes("utf-8"), password);
System.out.println("加密后:" + new String(result, "utf-8"));
// String baseStr = encoder.encodeToString(result);
// System.out.println("base64加密des密文:" + baseStr);
// byte[] resp = decoder.decode(baseStr.getBytes());
// System.out.println("base解码des密文:" + new String(resp));
byte[] decryResult = DES.decrypt(result, password);
System.out.println("解密后:" + new String(decryResult));
}
AES
public static byte[] encrypt(byte[] src, String password) throws Exception {
SecretKeySpec keySpec = getSecretKeySpec(password);
//创建一个密钥工厂,然后用它把DESKeySpec转换成
//cipher对象世纪完成加密操作
Cipher cipher = Cipher.getInstance("AES");
//用密钥初始化cipher对象
cipher.init(cipher.ENCRYPT_MODE, keySpec);
//现在,获取数据并加密
//正式执行加密操作
byte[] r = cipher.doFinal(src);
return encoder.encode(r);
}
public static byte[] decrypt(byte[] src, String password) throws Exception {
src = decoder.decode(src);
SecretKeySpec keySpec = getSecretKeySpec(password);
//创建一个密钥工厂,然后用它把DESKeySpec转换成
//cipher对象世纪完成加密操作
Cipher cipher = Cipher.getInstance("AES");
//用密钥初始化cipher对象
cipher.init(cipher.DECRYPT_MODE, keySpec);
//现在,获取数据并加密
//正式执行加密操作
byte[] r = cipher.doFinal(src);
return r;
}
private static SecretKeySpec getSecretKeySpec(String password) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(password.getBytes());
kgen.init(128, random);
SecretKey secretKey = kgen.generateKey();
SecretKeySpec keySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
return keySpec;
}
static final Base64.Decoder decoder = Base64.getDecoder();
static final Base64.Encoder encoder = Base64.getEncoder();
public static void main(String[] args) throws Exception {
String str = "代价密的书记和阿萨德法";
System.out.println("加密前:" + str);
//长度是8的倍数
String password = "1234567890123456";
byte[] result = AES.encrypt(str.getBytes(), password);
System.out.println("加密后:" + new String(result));
byte[] decryResult = AES.decrypt(result, password);
System.out.println("解密后:" + new String(decryResult));
}
非对称加密
RSA 引文rsa有长度限制 所以这里进行了数据进行分段加密
private static String RSA = "RSA";
private static final String CIPHER_INSTANCE = "RSA/ECB/PKCS1Padding";
static final Base64.Decoder decoder = Base64.getDecoder();
static final Base64.Encoder encoder = Base64.getEncoder();
public static Map getKeys(int len) throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(len);
KeyPair keyPair = kpg.generateKeyPair();
Key publicKey = keyPair.getPublic();
Key privateKey = keyPair.getPrivate();
String pubKey = encoder.encodeToString(publicKey.getEncoded());
String priKey = encoder.encodeToString(privateKey.getEncoded());
Map resultMap = new HashMap<>();
resultMap.put("publicKey", pubKey);
resultMap.put("privateKey", priKey);
return resultMap;
}
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoder.decode(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(keySpec);
return key;
}
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoder.decode(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
return key;
}
private static final String CHARSET_UTF_8 = "UTF-8";
public static String publicEncrypt(String data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return encoder.encodeToString(rsaCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET_UTF_8), publicKey.getModulus().bitLength()));
}
public static String privateDecrypt(String data, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(rsaCodec(cipher, Cipher.DECRYPT_MODE, decoder.decode(data), privateKey.getModulus().bitLength()), CHARSET_UTF_8);
}
public static String privateEncrypt(String data, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE);
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return encoder.encodeToString(rsaCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET_UTF_8), privateKey.getModulus().bitLength()));
}
public static String publicDecrypt(String data, RSAPublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaCodec(cipher, Cipher.DECRYPT_MODE, decoder.decode(data), publicKey.getModulus().bitLength()));
}
private static byte[] rsaCodec(Cipher cipher, int opmode, byte[] data, int keySize) throws Exception {
int maxBlock = 0;
if (opmode == Cipher.DECRYPT_MODE) {
maxBlock = keySize / 8;
} else {
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
while (data.length > offSet) {
if (data.length - offSet > maxBlock) {
buff = cipher.doFinal(data, offSet, maxBlock);
} else {
buff = cipher.doFinal(data, offSet, data.length - offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
byte[] resultData = out.toByteArray();
out.close();
return resultData;
}
public static void main(String[] args) throws Exception {
Map keyMap = getKeys(1024);
String publicKey = keyMap.get("publicKey");
String privateKey = keyMap.get("privateKey");
System.out.println("公钥:\n" + publicKey);
System.out.println("私钥:\n" + privateKey);
String data = "打开了发动机卡拉决定翻开了解放法赛季的开罗附近阿克萨拉丁教父卡角色快乐的房间卡拉斯决定开罗附近阿斯克里的解放卡拉斯酒店客房法思考的解放卡拉祭祀坑的反抗拉斯蒂芬巴角色等级阿vjaklvlzxjlcvjlkx 卡拉角色的开罗附近阿喀琉斯的发送到解放卡角色的看法";
System.out.println("明文:\n" + data);
System.out.println("明文大小:\n" + data.getBytes().length);
String encodeData = publicEncrypt(data, getPublicKey(publicKey));
System.out.println("密文:\n" + encodeData);
String decodeData = privateDecrypt(encodeData, getPrivateKey(privateKey));
System.out.println("解密:\n" + decodeData);
}
DSA
public static byte[] sign(byte[] src, byte[] dsaPrivateKey) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initSign(privateKey);
signature.update(src);
byte[] res = signature.sign();
return encoder.encode(res);
}
static final Base64.Decoder decoder = Base64.getDecoder();
static final Base64.Encoder encoder = Base64.getEncoder();
public static boolean verify(byte[] src,byte[] sign, byte[] dsaPublicKey) throws Exception {
sign= decoder.decode(sign);
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey);
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(publicKey);
signature.update(src);
return signature.verify(sign);
}
public static void main(String[] args) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate();
System.out.println("public:" + dsaPublicKey);
System.out.println("private:" + dsaPublicKey);
String str = "123456";
byte[] sign = sign(str.getBytes("utf-8"), dsaPrivateKey.getEncoded());
System.out.println("签名:" + new String(sign));
boolean r = verify(str.getBytes(),sign, dsaPublicKey.getEncoded());
System.out.println("验证签名:" + r);
}
private static String SRC_TEST = "dsa security";
public static void test() throws Exception {
// 1.初始化密钥
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate();
// 2.执行签名
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("DSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Signature signature = Signature.getInstance("SHA1withDSA");
signature.initSign(privateKey);
signature.update(SRC_TEST.getBytes());
byte[] res = signature.sign();
System.out.println("签名:" + new String(res));
// 3.验证签名
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("DSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
signature = Signature.getInstance("SHA1withDSA");
signature.initVerify(publicKey);
signature.update(SRC_TEST.getBytes());
boolean bool = signature.verify(res);
System.out.println("验证:" + bool);
}
Hash算法
HmacMD5 具体需要什么直接可以通过KeyGenerator.getInstance(); 来构造这里就不重复这里需要所密的是用base64 算法对key作处理这要就能保证key值的乱码显示和存储
private static final String HMAC_MD5 = "HmacMD5";
public static String initMacKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(HMAC_MD5);
SecretKey secretKey = keyGenerator.generateKey();
return Base64.getEncoder().encodeToString(secretKey.getEncoded());
}
public static String hashMsgCode(byte[] data, String key) throws Exception {
SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(key), HMAC_MD5);
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
return new String(Hex.encodeHex(mac.doFinal(data)));
}
public static void main(String[] args) throws Exception {
String macKey = initMacKey();
System.out.println("key:\n" + macKey);
String msg = "测试数据";
String msgCode = hashMsgCode(msg.getBytes(), macKey);
System.out.println("code:\n" + msgCode);
}
SHA
public static void main(String[] args) throws Exception{
String msg = "测试SHA";
String hashMsg = msgSafeBase(msg, "SHA-256");
System.out.println("msg:"+msg);
System.out.println("code:"+hashMsg);
}
private static final String UTF_8="UTF-8";
public static String msgSafeBase(String msg,String algorithem) throws Exception{
MessageDigest m = MessageDigest.getInstance(algorithem);
m.update(msg.getBytes(UTF_8));
byte[] s = m.digest();
return Hex.encodeHexString(s);
}