现在的位置: 首页 > 综合 > 正文

VC与JAVA DES加密算法互操作

2013年10月06日 ⁄ 综合 ⁄ 共 3989字 ⁄ 字号 评论关闭
     在实际开发过程中碰到了一个需要由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;
}

抱歉!评论已关闭.