最近对java实现对称加密算法产生兴趣,研究了网上的一些资料,通过亲自上机实践,写了基于java类库的对称加密算法实现代码,完整代码如下:
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class Encryptor {
public static final String ALGORITHM_DES = "DES";
public static final String ALGORITHM_THREEDES = "DESede";
public static final String ALGORITHM_AES = "AES";
public static final String ALGORITHM_BLOWFISH = "Blowfish";
private String algorithm;
private Key key;
private int blocksize;
/**
* 解密
*/
public byte[] decrypt(byte[] ivAndCiphertext) throws InvalidKeyException,
NoSuchAlgorithmException, NoSuchPaddingException,
InvalidAlgorithmParameterException, IllegalBlockSizeException,
BadPaddingException {
byte[] iv = new byte[this.blocksize];
byte[] c = new byte[ivAndCiphertext.length - this.blocksize];
System.arraycopy(ivAndCiphertext, 0, iv, 0, this.blocksize);
System.arraycopy(ivAndCiphertext, this.blocksize, c, 0,
ivAndCiphertext.length - this.blocksize);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
return cipher.doFinal(c);
}
/**
* 加密
*/
public byte[] encrypt(byte[] iv, byte[] plaintext)
throws InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance(algorithm + "/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
this.blocksize = cipher.getBlockSize();
byte[] c = cipher.doFinal(plaintext);
byte[] ivAndCiphertext = new byte[c.length + this.blocksize];
System.arraycopy(iv, 0, ivAndCiphertext, 0, this.blocksize);
System.arraycopy(c, 0, ivAndCiphertext, this.blocksize, c.length);
return ivAndCiphertext;
}
public Key generateKey(byte[] key) throws Exception {
if (key == null) {// 随机生成密钥
KeyGenerator keygen = KeyGenerator.getInstance(algorithm);
SecureRandom random = new SecureRandom();
keygen.init(random);
return keygen.generateKey();
} else {// 从一组固定的原始数据(也许是由口令或者随机键产生的)生成密钥
// SecretKeyFactory keyFactory =
// SecretKeyFactory.getInstance(algorithm);
// SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
// return keyFactory.generateSecret(keySpec);
Key secretKey = new SecretKeySpec(key, algorithm);
return secretKey;
}
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public void setKey(Key key) {
this.key = key;
}
}
public class Change {
// 将字符转化为字节
public static byte[] charToByte(char ch) {
int temp = (int) ch;
byte[] b = new byte[2];
// 将高8位放在b[0],将低8位放在b[1]
for (int i = 1; i > -1; i--) {
b[i] = (byte) (temp & 0xFF);// 低8位
// 向右移8位
temp >>= 8;
}
return b;
}
// 将字节转化为比特数组
public static byte[] byteToBitArray(byte b) {
// 强制转换成int?
int temp = (int) b;
byte[] result = new byte[8];
for (int i = 7; i > -1; i--) {
result[i] = (byte) (temp & 0x01);
temp >>= 1;
}
return result;
}
// 将二维比特数组转化为字节
public static byte bitToByteArray(byte[] b) {
byte result;
result = (byte) (b[7] | b[6] << 1 | b[5] << 2 | b[4] << 3 | b[3] << 4
| b[2] << 5 | b[1] << 6 | b[0] << 7);
return result;
}
public static void main(String[] args) {
for (byte b : charToByte('a')) {
System.out.println(b);
}
}
// 将字节转化为字符
public static char byteToChar(byte[] b) {
int s = 0;
if (b[0] > 0) {
s += b[0];
}
if (b[0] < 0) {
s += 256 + b[0];
}
s *= 256;
if (b[1] > 0) {
s += b[1];
}
if (b[1] < 0) {
s += 256 + b[1];
}
char ch = (char) s;
return ch;
}
public static String byteToHexString(byte b) {
String hex = "";
hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
return hex;
}
public static String bytesToHexString(byte[] bs) {
StringBuffer sb = new StringBuffer();
String hex = "";
for (int i = 0; i < bs.length; i++) {
hex = Integer.toHexString(bs[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex);
}
return sb.toString();
}
public static byte[] hexStringToBytes(String in) {
byte[] arrB = in.getBytes();
int iLen = arrB.length;
// 两个字符表示一个字节,所以字节数组长度是字符串长度除以2
byte[] arrOut = new byte[iLen / 2];
for (int i = 0; i < iLen; i = i + 2) {
String strTmp = new String(arrB, i, 2);
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
}
return arrOut;
}
}
import java.security.Key;
import org.junit.Test;
public class DESCoderTest {
@Test
public void test2() throws Exception {
Encryptor e = new Encryptor();
e.setAlgorithm(Encryptor.ALGORITHM_THREEDES);
Key key = e.generateKey(null);
System.out.println("密钥为(hex):"
+ Change.bytesToHexString(key.getEncoded()));
e.setKey(key);
String plaintext = "jlkasffdspfk阿斯达";
System.out.println("明文为:\n" + plaintext);
System.out.println("明文(hex)为:\n"
+ Change.bytesToHexString(plaintext.getBytes()));
String iv = "000a0a0a0a0202aa";
String ivAndCiphertext = Change.bytesToHexString(e.encrypt(Change
.hexStringToBytes(iv), plaintext.getBytes()));
System.out.println("加密后:\n" + ivAndCiphertext);
byte[] decrypt = e.decrypt(Change.hexStringToBytes(ivAndCiphertext));
System.out.println("解密后(hex):\n" + Change.bytesToHexString(decrypt));
System.out.println("解密后明文为:\n" + new String(decrypt));
decrypt = e.decrypt(Change.hexStringToBytes(ivAndCiphertext));
System.out.println("解密后(hex):\n" + Change.bytesToHexString(decrypt));
System.out.println("解密后明文为:\n" + new String(decrypt));
}
@Test
public void testAES() throws Exception {
Encryptor e = new Encryptor();
e.setAlgorithm(Encryptor.ALGORITHM_AES);
Key key = e.generateKey(null);
System.out.println("密钥为(hex):"
+ Change.bytesToHexString(key.getEncoded()));
e.setKey(key);
String plaintext = "jlkasffdspfk阿斯达";
System.out.println("明文为:\n" + plaintext);
System.out.println("明文(hex)为:\n"
+ Change.bytesToHexString(plaintext.getBytes()));
String iv = "000a0a0a0a0202aa000a0a0a0a0202aa";
String ivAndCiphertext = Change.bytesToHexString(e.encrypt(Change
.hexStringToBytes(iv), plaintext.getBytes()));
System.out.println("加密后:\n" + ivAndCiphertext);
byte[] decrypt = e.decrypt(Change.hexStringToBytes(ivAndCiphertext));
System.out.println("解密后(hex):\n" + Change.bytesToHexString(decrypt));
System.out.println("解密后明文为:\n" + new String(decrypt));
decrypt = e.decrypt(Change.hexStringToBytes(ivAndCiphertext));
System.out.println("解密后(hex):\n" + Change.bytesToHexString(decrypt));
System.out.println("解密后明文为:\n" + new String(decrypt));
}
}
测试结果如下:
密钥为(hex):5ee9858f5b8020f168a4f8d9e3e9405d4f7f2620f2ea4aab
明文为:
jlkasffdspfk阿斯达
明文(hex)为:
6a6c6b61736666647370666bb0a2cbb9b4ef
加密后:
000a0a0a0a0202aae094fd8543a17fd66b6c9f619a965dfe2e573d93dfa392ca
解密后(hex):
6a6c6b61736666647370666bb0a2cbb9b4ef
解密后明文为:
jlkasffdspfk阿斯达
解密后(hex):
6a6c6b61736666647370666bb0a2cbb9b4ef
解密后明文为:
jlkasffdspfk阿斯达
密钥为(hex):0bbd345a9d9f0007931d2b01dfb8533c
明文为:
jlkasffdspfk阿斯达
明文(hex)为:
6a6c6b61736666647370666bb0a2cbb9b4ef
加密后:
000a0a0a0a0202aa000a0a0a0a0202aa9e61715cb05a74fc7f6e2e63092391a56e9ad922e370a107f99335a32cafcb09
解密后(hex):
6a6c6b61736666647370666bb0a2cbb9b4ef
解密后明文为:
jlkasffdspfk阿斯达
解密后(hex):
6a6c6b61736666647370666bb0a2cbb9b4ef
解密后明文为:
jlkasffdspfk阿斯达