在实际开发过程中碰到了一个需要由JAVA加解密而用VC解密阅读的需求。因为算法也无需太复杂,故选择使用DES算法,这个两者都支持的算法。整个加解密的过程与功能很简单。但查阅相关的资料与调试花费了不少时间,下面贴出两段代码样例与大家共享:
JAVA代码:
public class DesSecurity {
BASE64Encoder encoder;
BASE64Decoder decoder;
Cipher enCipher;
Cipher deCipher;
/**
* @param key
加密密钥
* @param iv
初始化向量
* @throws Exception
*/
public DesSecurity(String key, String iv) throws Exception {
if (key == null) {
throw new NullPointerException("Parameter is null!");
}
initCipher(key.getBytes(), iv.getBytes());
}
private void initCipher(byte[] secKey, byte[] secIv) throws Exception {
//
创建MD5散列对象
MessageDigest md = MessageDigest.getInstance("MD5");
//
散列密钥
md.update(secKey);
//
获得DES密钥
DESKeySpec dks = new DESKeySpec(md.digest());
//
获得DES加密密钥工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
//
生成加密密钥
SecretKey key = keyFactory.generateSecret(dks);
//
创建初始化向量对象
IvParameterSpec iv = new IvParameterSpec(secIv);
AlgorithmParameterSpec paramSpec = iv;
//
为加密算法指定填充方式,创建加密会话对象
enCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
//
为加密算法指定填充方式,创建解密会话对象
deCipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
//
初始化加解密会话对象
enCipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
deCipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
encoder = new BASE64Encoder();
decoder = new BASE64Decoder();
}
/**
*
加密数据
* @param data
待加密二进制数据
* @return
经BASE64编码过的加密数据
* @throws Exception
*/
public String encrypt(byte[] data) throws Exception {
return encoder.encode(enCipher.doFinal(data));
}
/**
*
解密数据
* @param data
待解密字符串(经过BASE64编码)
* @return
解密后的二进制数据
* @throws Exception
*/
public byte[] decrypt(String data) throws Exception {
return deCipher.doFinal(decoder.decodeBuffer(data));
}
}
VC
代码:
//
参数:
// [IN] lpszKey
加密密钥
// [IN] lpszIv
初始化向量
DesSecurity::DesSecurity(LPTSTR lpszKey, LPTSTR lpszIv)
{
if (lpszKey == NULL || lpszIv == NULL) {
throw "Parameter is null!";
}
m_hKey = NULL;
init(lpszKey, lpszIv);
}
DesSecurity::~DesSecurity(void)
{
// Destroy the session key.
if(m_hKey != 0) CryptDestroyKey(m_hKey);
}
void DesSecurity::init(LPTSTR lpszKey, LPTSTR lpszIv) {
HCRYPTPROV hProv;
HCRYPTHASH hHash;
TCHAR szDebug[256];
DWORD dwLength;
try {
//
获得密钥容器
if(!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) {
sprintf(szDebug, "Error %x during CryptAcquireContext!/n", GetLastError());
throw szDebug;
}
//
创建MD5散列对象
if(!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) {
sprintf(szDebug, "Error %x during CryptCreateHash!/n", GetLastError());
throw szDebug;
}
//
散列密钥
dwLength = strlen(lpszKey);
if(!CryptHashData(hHash, (LPBYTE)lpszKey, dwLength, 0)) {
sprintf(szDebug, "Error %x during CryptHashData!/n", GetLastError());
throw szDebug;
}
//
创建会话密钥
if(!CryptDeriveKey(hProv, CALG_DES, hHash, 0, &m_hKey)) {
sprintf(szDebug, "Error %x during CryptDeriveKey!/n", GetLastError());
throw szDebug;
}
//
设置初始化向量.
if(!CryptSetKeyParam(m_hKey, KP_IV, (LPBYTE)lpszIv, 0)) {
sprintf(szDebug, "Error %x during CryptSetKeyParam!/n", GetLastError());
throw szDebug;
}
} catch(LPTSTR lpszDebug) {
// Destroy the hash object.
if(hHash != 0) CryptDestroyHash(hHash);
// Release the provider handle.
if(hProv != 0) CryptReleaseContext(hProv, 0);
throw lpszDebug;
}
}
//
//
功能: 解密数据
//
参数:
// [IN] lpszSrc
待解密数据(BASE64编码)
// [IN/OUT] lpszDst
存放解密后数据的缓冲区
// [IN/OUT] pnLen
输入时指缓冲区的长度,输出时指解密后数据的长度
//
返回值:
// TRUE
解密成功
// FALSE
解密失败
//
BOOL DesSecurity::Decode(LPTSTR lpszSrc, LPBYTE lpszDst, PINT pnLen) {
if (lpszSrc == NULL || lpszDst == NULL || pnLen == NULL) {
SetLastErrorEx(ERROR_INVALID_PARAMETER ,SLE_ERROR);
return false;
}
if (!Base64Decode(lpszSrc, _tcslen(lpszSrc), lpszDst, pnLen))
return false;
if (!CryptDecrypt(m_hKey, 0, true, 0, lpszDst, (DWORD*)pnLen))
return false;
return true;
}