密钥
Java中两种生成密钥的方式
- 利用已有key生成securekey
/**key(string)为已知密钥,利用密钥生成器,得到securekey**/
SecretKey securekey = null;
if(key == null){
key = "";
}
KeyGenerator keyGenerator = KeyGenerator.getInstance(DES);
keyGenerator.init(new SecureRandom(key.getBytes()));
securekey = keyGenerator.generateKey();
return securekey;
- 取key前8Byte作为securekey
// 生成一个可信任的随机数源
SecureRandom sr = new SecureRandom();
// 从原始密钥数据创建DESKeySpec对象
DESKeySpec dks = new DESKeySpec(key.getBytes());
// 创建一个密钥工厂,然后用它把DESKeySpec转换成SecretKey对象
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
SecretKey securekey = keyFactory.generateSecret(dks);
两种方式得到的key是不同的,对应的加密init方法。
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.ENCRYPT_MODE,securekey); //第一种
cipher.init(Cipher.ENCRYPT_MODE,securekey,sr); //第二种
由于key的不同,加密后的内容不同
其实写这篇博客是因为C#的原因
第二种方式对于C#与Java之间的互通是很好把握的
但是第一种方式呢,C#是无法使用类似KeyGenerator这样的密钥生成器,至少我还没有找到,希望对C#比较了解的童鞋们,给点帮助,谢谢!
Java完整代码示例:
import java.io.IOException;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/*该示例以第二种方式得到密钥*/
public class DesUtil {
private final static String DES = "DES";
/*入口*/
public static void main(String[] args) throws Exception {
String data = "123 456";
String key = "abcde67890";
System.err.println(encrypt(data, key));
System.err.println(decrypt(encrypt(data, key), key));
}
/*此方法作为参考,可替换加密和解密函数中的生成密钥方式,注意类型的匹配,string / byte */
public static Key getSecretKey(String key) throws Exception{
SecretKey securekey = null;
if(key == null){
key = "";
}
KeyGenerator keyGenerator = KeyGenerator.getInstance(DES);
keyGenerator.init(new SecureRandom(key.getBytes()));
securekey = keyGenerator.generateKey();
return securekey;
}
/**
* Description 根据键值进行加密
* @param data
* @param key 加密键byte数组
* @return
* @throws Exception
*/
public static String encrypt(String data, String key) throws Exception {
byte[] bt = encrypt(data.getBytes(), key.getBytes());
String strs = new BASE64Encoder().encode(bt);
return strs;
}
/**
* Description 根据键值进行解密
* @param data
* @param key 加密键byte数组
* @return
* @throws IOException
* @throws Exception
*/
public static String decrypt(String data, String key) throws IOException,Exception {
if (data == null)
return null;
BASE64Decoder decoder = new BASE64Decoder();
byte[] buf = decoder.decodeBuffer(data);
byte[] bt = decrypt(buf,key.getBytes());
return new String(bt);
}
/**
* Description 根据键值进行加密
* @param data
* @param key 加密键byte数组
* @return
* @throws Exception
*/
private static byte[] encrypt(byte[] data, byte[] key) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance(DES);
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);// 若使用第一种方式,可去掉,sr,相应的securekey调用参考方法
return cipher.doFinal(data);
}
/**
* Description 根据键值进行解密
* @param data
* @param key 加密键byte数组
* @return
* @throws Exception
*/
private static byte[] decrypt(byte[] data, byte[] key) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
SecretKey securekey = keyFactory.generateSecret(dks);
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance(DES);
// 用密钥初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, securekey, sr);//, sr
return cipher.doFinal(data);
}
}
Java与C#
这里就贴下C#的加密解密的示例代码
需要做一些说明
Java中DES加密默认ECB模式,C#中默认CBC模式,所以模式需要统一
C#中存在IV参数,如果是ECB模式,那么该参数也不会有所作用,所以可以忽略该值。
public static string strEncryptDES(string encryptString, string encryptKey)
{
try
{
byte[] btKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
byte[] btIV = Encoding.UTF8.GetBytes(encryptKey.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;//模式
des.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
byte[] inData = Encoding.UTF8.GetBytes(encryptString);
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
{
cs.Write(inData, 0, inData.Length);
cs.FlushFinalBlock();
}
return Convert.ToBase64String(ms.ToArray());
}
catch
{
return encryptString;
}
}
}
catch { }
return "DES加密出错";
}
public static string strDecryptDES(string encryptedString, string encryptKey)
{
byte[] btKey = Encoding.UTF8.GetBytes(encryptKey.Substring(0,8));
byte[] btIV = Encoding.UTF8.GetBytes(encryptKey.Substring(0,8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.Mode = CipherMode.ECB;
des.Padding = PaddingMode.PKCS7;
using (MemoryStream ms = new MemoryStream())
{
byte[] inData = Convert.FromBase64String(encryptedString);
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
{
cs.Write(inData, 0, inData.Length);
cs.FlushFinalBlock();
}
return Encoding.UTF8.GetString(ms.ToArray());
}
catch
{
return encryptedString;
}
}
}
主要就是C#与Java互通的问题