Java Tutorials-11-安全和加密

java.security 包提供了消息摘要/消息签名等算法.

将长度不固定的消息(message)作为输入参数,运行特定的Hash函数,生成固定长度的输出,这个输出就是Hash,也称为这个消息的消息摘要(Message Digest)
消息签名可以看成是在密钥加密的基础上的消息摘要, 消息摘要和消息签名的作用:

  1. 数据完整性检查
  2. 数据校验, 是否在传递过程中被篡改

消息摘要(Message Digest)

有如下几种消息摘要:

  • MD5, 任何消息都压缩为16字节(128位)的摘要(指纹), @Quection: 不推荐使用 MD5的原因是?
  • SHA1(属于SHA一代), 任何消息都压缩为20字节(160位)的摘要, 所以SHA-1共有最多2^120个摘要;
  • SHA256(属于SHA二代), 32字节(256位);
  • SHA512
  • MAC(或者HMAC算法), 在散列基础上增加了密钥;
  • BCrypt: 根据Blowfish加密算法所设计的密码散列函数

// MD5 & SHA
// 位于 java.security
MessageDigest alg = MessageDigest.getInstance("SHA-1"); // 也可以是MD5
byte[] bytes = new byte[10]; // bytes存入要计算摘要的信息
byte[] hash = alg.digest(bytes);

// HMAC
// 位于 javax.cypto.*
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5"); //初始化密钥生成器
SecretKey secretKey = keyGenerator.generateKey(); //产生密钥
byte[] encoded = secretKey.getEncoded(); //获取密钥
SecretKey restoreSecretKey = new SecretKeySpec(encoded, "HmacMD5"); //还原密钥
Mac mac = Mac.getInstance(restoreSecretKey.getAlgorithm()); //实例化MAC
mac.init(restoreSecretKey); //初始化MAC
byte[] hmacmd5Bytes = mac.doFinal(src.getBytes()); //执行摘要计算

消息签名(Message Signature)

  • DSA(数字签名)/RSA(公钥/私钥), 例如DSA是利用了对数值巨大的数字进行因数分解的困难性.

对称加密

  • DES
  • AES取代DES
  • Blowfish: 对称密钥区块加密算法
/***** JDK提供的 DES, 位于 java.security *****/
KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
keyGenerator.init(56);//设置长度
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();

//key转换, javax.cypto.*
DESKeySpec desKeySpec = new DESKeySpec(keyBytes);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey generateSecret = secretKeyFactory.generateSecret(desKeySpec);

//加密, javax.cypto.*
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, generateSecret);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println(Hex.encodeHexString(result));

//解密
cipher.init(Cipher.DECRYPT_MODE,generateSecret);//使用同一个key
result = cipher.doFinal(result);
System.out.println(new String(result));

blowfish & bcrypt

Encryption with BlowFish in Java - Stack Overflow

// blowfish
String Key = "Something";
byte[] KeyData = Key.getBytes();
SecretKeySpec KS = new SecretKeySpec(KeyData, "Blowfish");

// 加密
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, KS);
byte[] encryptedData = cipher.doFinal(toEncryptString.getBytes());

// 解密
Cipher cipher2 = Cipher.getInstance("Blowfish");
cipher2.init(Cipher.DECRYPT_MODE, KS);
byte[] decryptedData = cipher2.doFinal(encryptedData.getBytes());

BCrypt是基于Blowfish加密算法所设计的密码散列函数, 代码jBCrypt - strong password hashing for Java

// bcrypt
String password = "testpassword";
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12)); // 2的12次方
// 返回的hashed 字符串包括盐
// $2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
// 2a identifies the bcrypt algorithm version that was used.
// 10 is the cost factor; 2^10

// 验证
if (BCrypt.checkpw(candidate, hashed)) {
}

非对称加密

  • RSA: @todo