Just Keep RSA and AES

This commit is contained in:
xiaoyu830411
2012-08-27 15:57:47 +08:00
parent f755a614ac
commit 5891255dbb
17 changed files with 108 additions and 283 deletions
@@ -15,7 +15,7 @@ public abstract class AbstractDecrypter implements Decrypter {
/**
* DES, AES 密钥都有长度限制, 如果不够, 默认使用该字段补长
*/
protected static final String KEY_PADDING = "FOLLOW YOUR HEART. YOU CAN DO BEST THAN ANY ONE.";
public static final String KEY_PADDING = "FOLLOW YOUR HEART. YOU CAN DO BEST THAN ANY ONE.";
/**
* 传入密文, 返回明文
@@ -36,6 +36,10 @@ public class AesDecrypter extends AbstractDecrypter {
}
protected SecretKeySpec getSpec() {
if (this.spec == null) {
setKey("");
}
return this.spec;
}
@@ -1,46 +0,0 @@
package com.alibaba.druid.support.security.decryptor;
import com.alibaba.druid.pool.DecryptException;
import com.alibaba.druid.pool.Decrypter;
import com.alibaba.druid.pool.SensitiveParameters;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
/**
* 拷贝JBOSS的Blowfish解密
* @author Jonas Yang
*/
public class BlowfishDecrypter implements Decrypter {
public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException {
byte[] kbytes = "jaas is the way".getBytes();
SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
BigInteger n = new BigInteger(parameters.getPassword(), 16);
byte[] encoding = n.toByteArray();
if (encoding.length % 8 != 0) {
int length = encoding.length;
int newLength = ((length / 8) + 1) * 8;
int pad = newLength - length; //number of leading zeros
byte[] old = encoding;
encoding = new byte[newLength];
for (int i = old.length - 1; i >= 0; i--) {
encoding[i + pad] = old[i];
}
}
try {
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(encoding);
return new SensitiveParameters(parameters.getUrl(), parameters.getUsername(), new String(decryptedBytes));
} catch (Exception e) {
throw new DecryptException("Failed to decrypt JDBC password.", e);
}
}
}
@@ -1,63 +0,0 @@
package com.alibaba.druid.support.security.decryptor;
import com.alibaba.druid.pool.DecryptException;
import com.alibaba.druid.pool.SensitiveParameters;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
/**
* DES 解密器
*
* @author Jonas Yang
*/
public class DesDecrypter extends AbstractDecrypter {
private static final int KEY_LENGTH = 24;
private volatile SecretKey key;
public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException {
SecretKey key = getKey();
if (key == null) {
throw new DecryptException("No key.");
}
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, this.key);
String passwordPlainText = decrypt(cipher, parameters.getPassword());
return new SensitiveParameters(parameters.getUrl(), parameters.getUsername(), passwordPlainText);
} catch (Exception e) {
throw new DecryptException("Failed to decrypt JDBC parameters", e);
}
}
public void setKey(String key) {
if (key == null) {
throw new IllegalArgumentException("The key cannot be null");
}
if (key.length() < 24) {
key = KEY_PADDING.substring(0, KEY_LENGTH - key.length()) + key;
}
try {
byte[] keyBytes = key.getBytes();
DESKeySpec spec = new DESKeySpec(keyBytes);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
this.key = factory.generateSecret(spec);
} catch (Exception e) {
throw new IllegalArgumentException("Cannot get key.", e);
}
}
protected SecretKey getKey() {
return this.key;
}
}
@@ -22,15 +22,14 @@ import java.security.spec.X509EncodedKeySpec;
*/
public class RsaDecrypter extends AbstractDecrypter {
public static Log log = LogFactory.getLog(RsaDecrypter.class);
private static Log log = LogFactory.getLog(RsaDecrypter.class);
private static final String DEFAULT_PUBLIC_KEY_STRING = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHGwq7q2RmwuRgKxBypQHw0mYu4BQZ3eMsTrdK8E6igRcxsobUC7uT0SoxIjl1WveWniCASejoQtn/BY6hVKWsCAwEAAQ==";
private volatile PublicKey publicKey;
public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException {
PublicKey publicKey = getPublicKey();
if (publicKey == null) {
throw new DecryptException("No public Key.");
}
try {
Cipher cipher = Cipher.getInstance("RSA");
@@ -46,6 +45,10 @@ public class RsaDecrypter extends AbstractDecrypter {
}
protected PublicKey getPublicKey() {
if (this.publicKey == null) {
setPublicKeyString(DEFAULT_PUBLIC_KEY_STRING);
}
return this.publicKey;
}
@@ -54,14 +54,10 @@ public abstract class AbstractAction implements Action {
protected String readPassword() {
char[] keyChars = System.console().readPassword(this.prompt + "请输入密码[长度最大为" + this.maxKeyLength + "字节]: ");
if (keyChars == null) {
System.err.println("错误: 密码不能为空!");
return null;
keyChars = new char[0];
}
String keyString = new String(keyChars);
if (keyString == null) {
return null;
}
if (keyString.length() < this.minKeyLength || keyString.length() > this.maxKeyLength) {
System.err.println("错误: 密码长度要大于等于" + this.minKeyLength + ", 小于等于" + this.maxKeyLength + ".");
@@ -1,5 +1,7 @@
package com.alibaba.druid.support.security.tool;
import com.alibaba.druid.support.security.decryptor.AbstractDecrypter;
/**
* @author Jonas Yang
*/
@@ -7,7 +9,7 @@ public interface Action {
/**
* DES, AES 密钥都有长度限制, 如果不够, 默认使用该字段补长
*/
public String KEY_PADDING = "FOLLOW YOUR HEART. YOU CAN DO BEST THAN ANY ONE.";
public String KEY_PADDING = AbstractDecrypter.KEY_PADDING;
public String getId();
@@ -11,7 +11,7 @@ import javax.crypto.spec.SecretKeySpec;
public class AesAction extends AbstractAction {
public AesAction() {
super(6, 16, "AES");
super(0, 16, "AES");
}
@Override
@@ -1,47 +0,0 @@
package com.alibaba.druid.support.security.tool;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
/**
* @author Jonas Yang
*/
public class BlowfishAction implements Action {
@Override
public String getId() {
return "Blowfish";
}
public void execute() {
System.out.println();
String plainString = System.console().readLine("[Blowfish]请输入要需要加密的明文: ");
if (plainString == null) {
System.err.println("输入不能为空.");
return;
}
try {
String encryptedString = encrypt(plainString);
System.out.println("请记住以下的密文, 长度为[" + encryptedString.length() + "].");
System.out.println();
System.out.println(encryptedString);
System.out.println();
} catch (Exception e) {
System.out.println("加密出错.");
e.printStackTrace();
}
}
private String encrypt(String plainString) throws Exception {
byte[] kbytes = "jaas is the way".getBytes();
SecretKeySpec key = new SecretKeySpec(kbytes, "Blowfish");
Cipher cipher = Cipher.getInstance("Blowfish");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encoding = cipher.doFinal(plainString.getBytes());
BigInteger n = new BigInteger(encoding);
return n.toString(16);
}
}
@@ -1,37 +0,0 @@
package com.alibaba.druid.support.security.tool;
import com.alibaba.druid.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
/**
* @author Jonas Yang
*/
public class DesAction extends AbstractAction {
public DesAction() {
super(6, 24, "DES");
}
@Override
public String getId() {
return "DES";
}
public String encrypt(String keyString, String plainString) throws Exception {
DESKeySpec spec = new DESKeySpec(keyString.getBytes());
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
SecretKey key = factory.generateSecret(spec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(plainString.getBytes());
return Base64.byteArrayToBase64(encryptedBytes);
}
}
@@ -17,9 +17,7 @@ public class Main {
static {
int i = 1;
help.addAction(Integer.toString(i++), new RsaAction());
help.addAction(Integer.toString(i++), new DesAction());
help.addAction(Integer.toString(i++), new AesAction());
help.addAction(Integer.toString(i++), new BlowfishAction());
help.addAction("h", help);
help.addAction("q", new QuitAction());
}
@@ -12,6 +12,8 @@ import java.security.spec.PKCS8EncodedKeySpec;
*/
public class RsaAction implements Action {
private static final String DEFAULT_PRIVATE_KEY_STRING = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAocbCrurZGbC5GArEHKlAfDSZi7gFBnd4yxOt0rwTqKBFzGyhtQLu5PRKjEiOXVa95aeIIBJ6OhC2f8FjqFUpawIDAQABAkAPejKaBYHrwUqUEEOe8lpnB6lBAsQIUFnQI/vXU4MV+MhIzW0BLVZCiarIQqUXeOhThVWXKFt8GxCykrrUsQ6BAiEA4vMVxEHBovz1di3aozzFvSMdsjTcYRRo82hS5Ru2/OECIQC2fAPoXixVTVY7bNMeuxCP4954ZkXp7fEPDINCjcQDywIgcc8XLkkPcs3Jxk7uYofaXaPbg39wuJpEmzPIxi3k0OECIGubmdpOnin3HuCP/bbjbJLNNoUdGiEmFL5hDI4UdwAdAiEAtcAwbm08bKN7pwwvyqaCBC//VnEWaq39DCzxr+Z2EIk=";
@Override
public String getId() {
return "RSA";
@@ -28,47 +30,31 @@ public class RsaAction implements Action {
System.out.println("2. 创建 RSA 密钥");
String input = System.console().readLine("[RSA]请输入选项: ");
if (input == null || input.length() == 0) {
System.err.println("不是一个合法的输入.");
}
if ("1".equals(input)) {
encrypt();
return;
}
if ("2".equals(input)) {
} else if ("2".equals(input)) {
generateKeys();
} else {
System.err.println("不是一个合法的输入.");
}
}
private void encrypt() {
String filePath = System.console().readLine("[RSA]请输入私钥文件路径: ");
if (!new File(filePath).exists()) {
System.err.println("文件不存在[" + filePath + "]");
}
String filePath = System.console().readLine("[RSA]请输入私钥文件路径[如果直接回车将使用默认私钥]: ");
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream in = null;
try {
in = new FileInputStream(filePath);
byte[] b = new byte[512/8];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
} catch (Exception e) {
System.err.println("读取文件出错. " + e.getMessage());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
byte[] key = null;
if (filePath == null || filePath.length() == 0) {
key = Base64.base64ToByteArray(DEFAULT_PRIVATE_KEY_STRING);
} else {
try {
key = getPrivateKeyFromFile(filePath);
} catch (Exception e) {
System.err.println("读取文件出错. " + e.getMessage());
return;
}
}
byte[] key = out.toByteArray();
String plainString = System.console().readLine("[RSA]请输入要需要加密的明文: ");
try {
@@ -91,7 +77,46 @@ public class RsaAction implements Action {
}
}
private byte[] getPrivateKeyFromFile(String filePath) throws IOException {
if (!new File(filePath).exists()) {
System.err.println("文件不存在[" + filePath + "]");
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream in = null;
try {
in = new FileInputStream(filePath);
byte[] b = new byte[512/8];
int len = 0;
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
return out.toByteArray();
}
private void generateKeys() {
System.out.println();
System.out.println("[RSA]请选择密钥长度: \n1. 512 \n2. 1024 \n3. 2048");
String keySizeString = System.console().readLine("[RSA]请输入选项: ");
int keySize = 512;
if ("1".equals(keySizeString) || "2".equals(keySizeString) || "3".equals(keySizeString)) {
int power = (Integer.valueOf(keySizeString) - 1);
keySize = keySize << power;
} else {
System.err.println("不是一个合法的输入.");
return;
}
String input = System.console().readLine("[RSA]请输入输出路径: ");
if (input == null) {
input = "";
@@ -99,7 +124,7 @@ public class RsaAction implements Action {
try {
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(1024, new SecureRandom());
gen.initialize(keySize, new SecureRandom());
KeyPair pair = gen.generateKeyPair();
String privateKeyPath = input + ".private.key";
@@ -128,4 +153,23 @@ public class RsaAction implements Action {
}
}
}
public static void main(String[] args) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream in = null;
try {
in = new FileInputStream("/Users/yangkingsel/druid.public.key");
byte[] buf = new byte[512/8];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
System.out.println(Base64.byteArrayToBase64(out.toByteArray()));
} finally {
if (in != null) {
in.close();
}
}
}
}
@@ -1,8 +1,6 @@
package com.alibaba.druid.bvt.support.security;
import com.alibaba.druid.support.security.decryptor.AesDecrypterTest;
import com.alibaba.druid.support.security.decryptor.BlowfishDecrypterTest;
import com.alibaba.druid.support.security.decryptor.DesDecrypterTest;
import com.alibaba.druid.support.security.decryptor.RsaDecrypterTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -13,9 +11,7 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
AesDecrypterTest.class,
DesDecrypterTest.class,
RsaDecrypterTest.class,
BlowfishDecrypterTest.class
RsaDecrypterTest.class
})
public class DecrypterTestSuite {
}
@@ -18,4 +18,12 @@ public class AesDecrypterTest {
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
}
@Test
public void testDecryptWithEmptyKey() throws DecryptException {
AesDecrypter decrypter = new AesDecrypter();
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", "AzgdbVU3SIK6A8+0qg+Btg=="));
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
}
}
@@ -1,20 +0,0 @@
package com.alibaba.druid.support.security.decryptor;
import com.alibaba.druid.pool.DecryptException;
import com.alibaba.druid.pool.SensitiveParameters;
import junit.framework.Assert;
import org.junit.Test;
/**
* @author Jonas Yang
*/
public class BlowfishDecrypterTest {
@Test
public void testDecrypt() throws DecryptException {
BlowfishDecrypter decrypter = new BlowfishDecrypter();
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", "64c5fd2979a86168"));
Assert.assertEquals("It is not same.", "123456", parameters.getPassword());
}
}
@@ -1,21 +0,0 @@
package com.alibaba.druid.support.security.decryptor;
import com.alibaba.druid.pool.DecryptException;
import com.alibaba.druid.pool.SensitiveParameters;
import junit.framework.Assert;
import org.junit.Test;
/**
* @author Jonas Yang
*/
public class DesDecrypterTest {
@Test
public void testDecrypt() throws DecryptException {
DesDecrypter decrypter = new DesDecrypter();
decrypter.setKey("123456");
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", "rIsr38vJDyQ="));
Assert.assertEquals("It is not same", parameters.getPassword(), "xiaoyu");
}
}
@@ -61,4 +61,12 @@ public class RsaDecrypterTest {
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
}
@Test
public void testDecryptWithEmptyKey() throws DecryptException {
RsaDecrypter decrypter = new RsaDecrypter();
SensitiveParameters parameters = decrypter.decrypt(new SensitiveParameters("", "", "OJfUm6WCHi7EuXqE6aEc+Po2xFrAGBeSNy8O2jWhV2FTG8/5kbRRr2rjNKhptlevm/03Y0048P7h88gdUOXAYg=="));
Assert.assertEquals("It is not same.", "xiaoyu", parameters.getPassword());
}
}