这篇博文的前两节(1/3,2/3)已经介绍了如何在不安全网络环境下面相互认证双方的身份(建立信任的连接),以及在此基础上进行可靠的密钥协商(DH算法)。
这一节将介绍如何使用协商好的密钥对通道上流淌的数据进行加密。我将使用AES作为对称密钥的算法,密钥强度:128位。这个过程可以简单概括成下面两个步骤:
- 利用协商好的key创建一个可以用于加密和解密的Aes Cipher;
- 使用这个cipher对一个byte数组进行加密和解密。
直接上代码吧:
/**
* 使用AES 128bit 算法进行加密和解密的工具类
*
* @author atlas
* @date 2012-9-18
*/
public class AESCipher {
private static final int bsize = 16;
private static final int ivsize = 16;
private Cipher dCipher;
private Cipher eCipher;
private AESCipher(Cipher dCipher, Cipher eCipher) {
this.eCipher = eCipher;
this.dCipher = dCipher;
}
public static AESCipher getInstance(byte[] key) throws CryptoException {
String pad = "PKCS5Padding";
try {
byte[] tmpKey = ChecksumUtil.getChecksumAsBytes("md5", key);
byte[] tmpIV = new byte[ivsize];
if (key.length <= ivsize) {
System.arraycopy(key, 0, tmpKey, 0, key.length);
} else if (key.length > ivsize) {
System.arraycopy(key, 0, tmpIV, 0, tmpIV.length);
}
SecretKeySpec keyspec = new SecretKeySpec(tmpKey, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(tmpIV);
Cipher dcipher = Cipher.getInstance("AES/CBC/" + pad);
Cipher ecipher = Cipher.getInstance("AES/CBC/" + pad);
ecipher.init(Cipher.ENCRYPT_MODE, keyspec, ivSpec);
dcipher.init(Cipher.DECRYPT_MODE, keyspec, ivSpec);
return new AESCipher(dcipher, ecipher);
} catch (Exception e) {
throw new CryptoException("initializing AESCipher fail.", e);
}
}
/**
*
* @param str
* @return
* @throws CryptoException
*/
public String encrypt(String str) throws CryptoException {
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = this.eCipher.doFinal(utf8);
// Encode bytes to hex string
return StringUtils.bytesToHex(enc);
} catch (Exception e) {
throw new CryptoException("encrypt failed.", e);
}
}
public String decrypt(String str) throws CryptoException {
try {
byte[] dec = StringUtils.hexToBytes(str);
// Decrypt
byte[] utf8 = this.dCipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
} catch (Exception e) {
throw new CryptoException("decrypt failed.", e);
}
}
public byte[] encrypt(byte[] message) throws CryptoException {
try {
// Encrypt
return this.eCipher.doFinal(message);
} catch (Exception e) {
throw new CryptoException("encrypt failed.", e);
}
}
/**
* 这个方法是为了尽可能少的减少内存拷贝,input buffer和output
* buffer可以是一个byte数组,不过调用者需要保证output可以输出数据的长度要足够大,即能够容纳加密后的padding。
* 这个padding不会超过 {@link #getBsize() }-1
*
* @param input
* 待加密的buffer
* @param inputOffset
* 待加密的数据在input buffer中的起始位置(从0开始)
* @param inputLen
* 待加密的数据的长度,不超过(input.length-inputOffset).
* @param output
* 加密后的数据的输出buffer。
* @param outputOffset
* 输出buffer的起始位置。
* @return 在output里面实际解密的数据长度
*
* @throws ShortBufferException
* 如果output buffer太小,无法容纳输出结果
*/
public int encrypt(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset) throws CryptoException {
try {
return eCipher.doFinal(input, inputOffset, inputLen, output,
outputOffset);
} catch (Exception e) {
throw new CryptoException("encryption failed", e);
}
}
/**
* 这个方法是为了尽可能少的减少内存拷贝,input buffer和output buffer可以是同一个byte数组。
*
* @param input
* 待解密的buffer
* @param inputOffset
* 待解密的数据在input buffer中的起始位置(从0开始)
* @param inputLen
* 待解密的数据的长度,不超过(input.length-inputOffset).
* @param output
* 解密后的数据的输出buffer。
* @param outputOffset
* 输出buffer的起始位置。
* @return 在output里面实际解密的数据长度
* @throws ShortBufferException
* 如果output buffer太小,无法容纳输出结果
*/
public int decrypt(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset) throws CryptoException {
try {
return dCipher.doFinal(input, inputOffset, inputLen, output,
outputOffset);
} catch (Exception e) {
throw new CryptoException("decryption failed", e);
}
}
/**
* 返回需要的padding的长度
*
* @param len
* @return
*/
public int pad(int len) {
return eCipher.getOutputSize(len) - len;
}
public byte[] decrypt(byte[] message) throws CryptoException {
try {
// Decrypted
byte[] decrypted = this.dCipher.doFinal(message);
return decrypted;
} catch (Exception e) {
throw new CryptoException("decrypt failed.", e);
}
}
}
几个工具类的代码我就不贴了。
分享到:
相关推荐
mysql-connector-java-5.1.27.jar mysql-connector-java-5.1.27.jar
mysql-connector-java-5.1.40-bin.jar连接器,用于在hive和mysql的数据库连接
mysql驱动包 mysql-connector-java-5.1.13-bin.jar 方便快捷获取。。。
<artifactId>aliyun-java-sdk-core</artifactId> <version>3.2.2</version> </dependency> 如此引用即可,更多关于阿里云短信发送相关请参考http://blog.csdn.net/niaoer2010/article/details/78036664
5.6.20 最新JDBC mysql-connector-java-5.1.32-bin.jar
mysql-connector-java-5.1.42-bin.jar 官网下载的驱动
jdbc链接mysql数据库的jar包(mysql-connector-java-5.0.8-bin.jar)
这是MySQL最新的jar,mysql-connector-java-8.0.18.jar
mysql-connector-java-5.1.30-bin.jar 最新的mysql jdbc
mysql 的jdbc 驱动。mysql-connector-java-5.1.38-bin.jar
mysql-connector-java-8.0.11.jar连接器,用于在hive和mysql的数据库连接
JAVA连MySQL驱动mysql-connector-java-5.1.25.jar
使用C3P0额外依赖的一个jar包 :mchange-commons-java-0.2.3.4.jar
用于连接mysql数据库. mysql-connector-java-5.0.4-bin.jar
MySQL官方提供的驱动包 mysql-connector-java-5.1.30.zip
jdbc的驱动jar包,有需要的童鞋自取。
java-1.7.0-openjdk devel rpm
mysql-connector-java-5.1.31-bin
java图片处理工具类JAR包 java-image-scalingjar
最全面关于J2EE跨域资源共享的解决方案以及所需要依赖的Jar包,cors-filter-1.7.jar,java-property-utils-1.9.jar, tomcat配置方法连接 http://bsxsb.com/index.php/2015/08/07/tomcat下通过cors实现跨域配置/