mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
Encrypt tool and Decrypter
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package com.alibaba.druid.pool;
|
||||
|
||||
/**
|
||||
* 加密出错
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class DecryptException extends Exception {
|
||||
public DecryptException() {
|
||||
super(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
public DecryptException(String s) {
|
||||
super(s); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
public DecryptException(String s, Throwable throwable) {
|
||||
super(s, throwable); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
public DecryptException(Throwable throwable) {
|
||||
super(throwable); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.alibaba.druid.pool;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 解密敏感参数
|
||||
* 使用解密器 只要简单实现这个类就可以了。
|
||||
*
|
||||
* public class MyDecrypter implement Decrypter {
|
||||
* public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException {
|
||||
* String url = ....;
|
||||
* String username = ....;
|
||||
* String password = ....;
|
||||
*
|
||||
* return new SensitiveParameters(url, username, password);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* DruidDataSource dataSource = new DruidDataSource();
|
||||
* //设置DataSource的其他参数
|
||||
* dataSource.setDecrypter(new MyDecrypter);
|
||||
*
|
||||
* [下面是Spring的配置]
|
||||
*
|
||||
* <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
|
||||
* <property name="url" value="${jdbc_url}" />
|
||||
* <property name="username" value="${jdbc_user}" />
|
||||
* <property name="password" value="${jdbc_password}" />
|
||||
* <b><property name="decrypter"><ref bean="myDecrypter"/></property></b>
|
||||
* </bean>
|
||||
*
|
||||
* <bean id="myDecrypter" class="MyDecrypter"/>
|
||||
*
|
||||
* </pre>
|
||||
* <br/>
|
||||
* <b>默认下, Druid 已经实现了AES, DES, RSA, Blowfish(兼容JBOSS)等加解密. AES, DES 解密的密文必须是通过Druid Tool的加密工具生成的</b>
|
||||
* <br/>
|
||||
* <b>使用加密工具: java -cp druid-x.x.x.jar com.alibaba.druid.support.security.tool.Main</b>
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public interface Decrypter {
|
||||
|
||||
/**
|
||||
* 返回一个解密后的(明文)参数
|
||||
* @param parameters 密文参数
|
||||
* @return
|
||||
* @throws DecryptException 解密失败会抛出该异常
|
||||
*/
|
||||
public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.alibaba.druid.pool;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 存放, 数据库的关键参数:URL, 用户名, 密码
|
||||
* 如果存放的是明文, 请尽可能缩短实例的作用域
|
||||
* </pre>
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class SensitiveParameters {
|
||||
private transient final String url;
|
||||
|
||||
private transient final String username;
|
||||
|
||||
private transient final String password;
|
||||
|
||||
public SensitiveParameters(String url, String username, String password) {
|
||||
this.url = url;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.alibaba.druid.support.security.decryptor;
|
||||
|
||||
import com.alibaba.druid.pool.Decrypter;
|
||||
import com.alibaba.druid.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
/**
|
||||
* 加密抽象类
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public abstract class AbstractDecrypter implements Decrypter {
|
||||
|
||||
/**
|
||||
* DES, AES 密钥都有长度限制, 如果不够, 默认使用该字段补长
|
||||
*/
|
||||
protected static final String KEY_PADDING = "FOLLOW YOUR HEART. YOU CAN DO BEST THAN ANY ONE.";
|
||||
|
||||
/**
|
||||
* 传入密文, 返回明文
|
||||
* @param cipher 解密器
|
||||
* @param cipherString 密文
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
protected String decrypt(Cipher cipher, String cipherString) throws Exception {
|
||||
if (cipherString == null || cipherString.length() == 0) {
|
||||
return cipherString;
|
||||
}
|
||||
|
||||
byte[] cipherBytes = Base64.base64ToByteArray(cipherString);
|
||||
byte[] plainBytes = cipher.doFinal(cipherBytes);
|
||||
|
||||
return new String(plainBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
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.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* AES 解密器
|
||||
*
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class AesDecrypter extends AbstractDecrypter {
|
||||
|
||||
private final static int KEY_LENGTH = 16; //128
|
||||
|
||||
private volatile SecretKeySpec spec;
|
||||
|
||||
public SensitiveParameters decrypt(SensitiveParameters parameters) throws DecryptException {
|
||||
SecretKeySpec spec = getSpec();
|
||||
if (spec == null) {
|
||||
throw new DecryptException("No key.");
|
||||
}
|
||||
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(Cipher.DECRYPT_MODE, spec);
|
||||
|
||||
String passwordPlainText = decrypt(cipher, parameters.getPassword());
|
||||
|
||||
return new SensitiveParameters(parameters.getUrl(), parameters.getUsername(), passwordPlainText);
|
||||
} catch (Exception e) {
|
||||
throw new DecryptException("Failed to decrypt JDBC password’", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected SecretKeySpec getSpec() {
|
||||
return this.spec;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("The key cannot be null");
|
||||
}
|
||||
|
||||
if (key.length() < 16) {
|
||||
key = KEY_PADDING.substring(0, KEY_LENGTH - key.length()) + key;
|
||||
}
|
||||
|
||||
this.spec = new SecretKeySpec(key.getBytes(), "AES");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.alibaba.druid.support.security.decryptor;
|
||||
|
||||
import com.alibaba.druid.pool.DecryptException;
|
||||
import com.alibaba.druid.pool.SensitiveParameters;
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.security.cert.Certificate;
|
||||
|
||||
/**
|
||||
* RSA 解密器, 支持证书
|
||||
*
|
||||
*/
|
||||
public class RsaDecrypter extends AbstractDecrypter {
|
||||
|
||||
public static Log log = LogFactory.getLog(RsaDecrypter.class);
|
||||
|
||||
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");
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
String passwordPlainText = decrypt(cipher, parameters.getPassword());
|
||||
|
||||
return new SensitiveParameters(parameters.getUrl(), parameters.getUsername(), passwordPlainText);
|
||||
} catch (DecryptException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new DecryptException("Failed to decrypt JDBC parameters", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected PublicKey getPublicKey() {
|
||||
return this.publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKeyString(String publicKeyString) {
|
||||
if (publicKeyString == null) {
|
||||
throw new IllegalArgumentException("The publicKeyString cannot be null");
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] publicKeyBytes = Base64.base64ToByteArray(publicKeyString);
|
||||
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
this.publicKey = keyFactory.generatePublic(x509KeySpec);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to get public key", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPublicKeyFile(String publicKeyFile) {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(publicKeyFile);
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
int len = 0;
|
||||
byte[] b = new byte[512/8];
|
||||
while ((len = in.read(b)) != -1) {
|
||||
out.write(b, 0, len);
|
||||
}
|
||||
|
||||
byte[] publicKeyBytes = out.toByteArray();
|
||||
X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
this.publicKey = factory.generatePublic(spec);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to get public key", e);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setX509File(String x509File) {
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(x509File);
|
||||
|
||||
CertificateFactory factory = CertificateFactory.getInstance("X.509");
|
||||
Certificate cer = factory.generateCertificate(in);
|
||||
this.publicKey = cer.getPublicKey();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Failed to get public key", e);
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
log.warn("Cannot close file [" + x509File + "] in initialized public key.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public abstract class AbstractAction implements Action {
|
||||
private int minKeyLength;
|
||||
|
||||
private int maxKeyLength;
|
||||
|
||||
private String prompt;
|
||||
|
||||
public AbstractAction(int minKeyLength, int maxKeyLength, String prompt) {
|
||||
if (minKeyLength < 0 || maxKeyLength < 0) {
|
||||
throw new IllegalArgumentException("The key length must be a positive.");
|
||||
}
|
||||
|
||||
if (maxKeyLength < minKeyLength) {
|
||||
throw new IllegalArgumentException("The max length of key cannot be less than min length.");
|
||||
}
|
||||
|
||||
this.minKeyLength = minKeyLength;
|
||||
this.maxKeyLength = maxKeyLength;
|
||||
this.prompt = "[" + prompt + "]";
|
||||
}
|
||||
|
||||
protected abstract String encrypt(String keyString, String plainString) throws Exception;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println();
|
||||
|
||||
String keyString = readPassword();
|
||||
if (keyString == null) return;
|
||||
|
||||
String plainString = System.console().readLine(this.prompt + "请输入要需要加密的明文: ");
|
||||
if (plainString == null) {
|
||||
System.err.println("输入不能为空.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String encryptedString = encrypt(keyString, plainString);
|
||||
System.out.println("请记住以下的密文, 长度为[" + encryptedString.length() + "].");
|
||||
System.out.println();
|
||||
System.out.println(encryptedString);
|
||||
System.out.println();
|
||||
} catch (Exception e) {
|
||||
System.out.println("加密出错.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected String readPassword() {
|
||||
char[] keyChars = System.console().readPassword(this.prompt + "请输入密码[长度最大为" + this.maxKeyLength + "字节]: ");
|
||||
if (keyChars == null) {
|
||||
System.err.println("错误: 密码不能为空!");
|
||||
return null;
|
||||
}
|
||||
|
||||
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 + ".");
|
||||
return null;
|
||||
}
|
||||
|
||||
keyString = KEY_PADDING.substring(0, this.maxKeyLength - keyString.length()) + keyString;
|
||||
|
||||
return keyString;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public interface Action {
|
||||
/**
|
||||
* DES, AES 密钥都有长度限制, 如果不够, 默认使用该字段补长
|
||||
*/
|
||||
public String KEY_PADDING = "FOLLOW YOUR HEART. YOU CAN DO BEST THAN ANY ONE.";
|
||||
|
||||
public String getId();
|
||||
|
||||
public void execute();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class AesAction extends AbstractAction {
|
||||
|
||||
public AesAction() {
|
||||
super(6, 16, "AES");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "AES";
|
||||
}
|
||||
|
||||
protected String encrypt(String keyString, String plainString) throws Exception {
|
||||
SecretKeySpec spec = new SecretKeySpec(keyString.getBytes(), "AES");
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, spec);
|
||||
|
||||
byte[] encryptedBytes = cipher.doFinal(plainString.getBytes());
|
||||
|
||||
return new BASE64Encoder().encode(encryptedBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
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 new BASE64Encoder().encode(encryptedBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class HelpAction implements Action {
|
||||
|
||||
private List<ActionDesc> list = new ArrayList<ActionDesc>();
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "HELP";
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
System.out.println();
|
||||
for (ActionDesc desc : list) {
|
||||
System.out.println(desc.getKey() + ". " + desc.getAction().getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void addAction(String key, Action action) {
|
||||
this.list.add(new ActionDesc(key, action));
|
||||
}
|
||||
|
||||
public Action getAction(String key) {
|
||||
for (ActionDesc desc : list) {
|
||||
if (desc.getKey().equals(key)) {
|
||||
return desc.getAction();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ActionDesc {
|
||||
private final String key;
|
||||
private final Action action;
|
||||
|
||||
public ActionDesc(String key, Action action) {
|
||||
this.key = key;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Druid 提供的加密工具. 如下运行
|
||||
*
|
||||
* <b>java -cp druid-x.x.x.jar com.alibaba.druid.support.security.tool.Main</b>
|
||||
*
|
||||
* </pre>
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class Main {
|
||||
private static boolean isEnd = false;
|
||||
|
||||
private static HelpAction help = new HelpAction();
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
header();
|
||||
help.execute();
|
||||
|
||||
while(!isEnd) {
|
||||
String input = System.console().readLine("请输入选项: ");
|
||||
input = input.toLowerCase();
|
||||
Action action = help.getAction(input);
|
||||
if (action == null) {
|
||||
System.err.println(input + " 不是一个合法的选项.[如需要帮助请输入 h]");
|
||||
continue;
|
||||
} else {
|
||||
action.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void header() {
|
||||
System.out.println("**************************************");
|
||||
System.out.println("* *");
|
||||
System.out.println("* Druid 加密工具 *");
|
||||
System.out.println("* *");
|
||||
System.out.println("**************************************");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class QuitAction implements Action {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "QUIT";
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
foot();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void foot() {
|
||||
System.out.println("**************************************");
|
||||
System.out.println("* *");
|
||||
System.out.println("* 再 见 了 *");
|
||||
System.out.println("* *");
|
||||
System.out.println("**************************************");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.alibaba.druid.support.security.tool;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
/**
|
||||
* @author Jonas Yang
|
||||
*/
|
||||
public class RsaAction implements Action {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return "RSA";
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
help();
|
||||
}
|
||||
|
||||
private void help() {
|
||||
System.out.println();
|
||||
System.out.println("RSA 选项: ");
|
||||
System.out.println("1. 通过私钥加密");
|
||||
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)) {
|
||||
generateKeys();
|
||||
}
|
||||
}
|
||||
|
||||
private void encrypt() {
|
||||
String filePath = System.console().readLine("[RSA]请输入私钥文件路径: ");
|
||||
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);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("读取文件出错. " + e.getMessage());
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] key = out.toByteArray();
|
||||
String plainString = System.console().readLine("[RSA]请输入要需要加密的明文: ");
|
||||
|
||||
try {
|
||||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(key);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
PrivateKey privateKey = factory.generatePrivate(spec);
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
|
||||
byte[] encryptedBytes = cipher.doFinal(plainString.getBytes());
|
||||
String encryptedString = new BASE64Encoder().encode(encryptedBytes);
|
||||
|
||||
System.out.println("请记住以下的密文, 长度为[" + encryptedString.length() + "].");
|
||||
System.out.println();
|
||||
System.out.println(encryptedString);
|
||||
System.out.println();
|
||||
} catch (Exception e) {
|
||||
System.err.println("加密错误. ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateKeys() {
|
||||
String input = System.console().readLine("[RSA]请输入输出路径: ");
|
||||
if (input == null) {
|
||||
input = "";
|
||||
}
|
||||
|
||||
try {
|
||||
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
|
||||
gen.initialize(1024, new SecureRandom());
|
||||
KeyPair pair = gen.generateKeyPair();
|
||||
|
||||
String privateKeyPath = input + ".private.key";
|
||||
saveKey(pair.getPrivate(), privateKeyPath);
|
||||
|
||||
String publicKeyPath = input + ".public.key";
|
||||
saveKey(pair.getPublic(), publicKeyPath);
|
||||
|
||||
System.out.println("Private Key: " + privateKeyPath);
|
||||
System.out.println("public Key: " + publicKeyPath);
|
||||
System.out.println();
|
||||
} catch (Exception e) {
|
||||
System.err.println("[RSA]创建 RSA 密钥出错. " + e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void saveKey(Key key, String path) throws Exception {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
out = new FileOutputStream(path);
|
||||
out.write(key.getEncoded());
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user