怎么把mysql数据库中现有的数据进行des加密,加密后的结果和java中des加密的结果一样。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么把mysql数据库中现有的数据进行des加密,加密后的结果和java中des加密的结果一样。相关的知识,希望对你有一定的参考价值。

最近需要对数据进行加密/解密, 因此选用了CryptoJS库, 对数据做DES算法的加密/解密

首选查看官方示例, 将密文进行Base64编码, 掉进一个大坑
<script src="htt p:/ /crypto-js.googlecod e.c om/svn/tags/3.1.2/build/rollups/tripledes.js"></script>
<script>
var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase");
// ciphertext changed every time you run it
// 加密的结果不应该每次都是一样的吗?
console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64));
var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase");
console.log(decrypted.toString(CryptoJS.enc.Utf8));
</script>

对这些加密算法不了解, 只能求助Google
des encrypion: js encrypted value does not match the java encrypted value
In cryptoJS you have to convert the key to hex and useit as word just like above (otherwise it will be considered as passphrase)
For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key.

原来是我指定key的方式不对, 直接将字符串做为参数, 想当然的以为这就是key, 其实不然, CryptoJS会根据这个字符串算出真正的key和IV(各种新鲜名词不解释, 问我也没用, 我也不懂 -_-")

那么我们只需要将key和iv对应的字符串转成CryptoJS的WordArray类型, 在DES加密时做为参数传入即可, 这样对Message这个字符串加密, 每次得到的密文都是YOa3le0I+dI=
var keyHex = CryptoJS.enc.Utf8.parse('abcd1234');
var ivHex = CryptoJS.enc.Utf8.parse('inputvec');
var encrypted = CryptoJS.DES.encrypt('Message', keyHex, iv: ivHex );

这样是不是就万事OK了? 哪有, 谁知道这坑是一个接一个啊.
我们再试试Java这边的DES加密是不是和这个结果一样, 具体实现请参考Simple Java Class to DES Encrypt Strings

果真掉坑里了, Java通过DES加密Message这个字符串得到的结果是8dKft9vkZ4I=和CryptoJS算出来的不一样啊...亲

继续求助Google
C# and Java DES Encryption value are not identical
SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES.(JCA Doc)
This means that in the case of the SunJCE provider,
Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");
and
Cipher c1 = Cipher.getInstance("DES");
are equivalent statements.

原来是CryptoJS进行DES加密时, 默认的模式和padding方式和Java默认的不一样造成的, 必须使用ECB mode和PKCS5Padding, 但是CryptoJS中只有Pkcs7, 不管了, 试试看...
<script src="htt p:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/rollups/tripledes.js"></script>
<script src="ht tp:/ /crypto-js.googleco de.c om/svn/tags/3.1.2/build/components/mode-ecb.js"></script>
<script>
var keyHex = CryptoJS.enc.Utf8.parse('abcd1234');
var encrypted = CryptoJS.DES.encrypt('Message', keyHex,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
);
console.log(encrypted.toString(), encrypted.ciphertext.toString(CryptoJS.enc.Base64));
</script>

咦...使用Pkcs7能得到和Java DES一样的结果了, 哇塞...好神奇
那我们试试统一Java也改成Cipher.getInstance("DES/ECB/PKCS7Padding")试试, 结果得到一个大大的错误
Error:java.security.NoSuchAlgorithmException: Cannot find any provider supporting DES/ECB/PKCS7Padding

没办法, 继续Google
java.security.NoSuchAlgorithmException: Cannot find any provider supporting AES/ECB/PKCS7PADDING
I will point out that PKCS#5 and PKCS#7 actually specify exactly the same type of padding (they are the same!), but it's called #5 when used in this context. :)

这位大侠给出的解释是: PKCS#5和PKCS#7是一样的padding方式, 对加密算法一知半解, 我也只能暂且认可这个解释了.

忙完了DES的加密, 接下来就是使用CryptoJS来解密了. 我们需要直接解密DES加密后的base64密文字符串. CryptoJS好像没有提供直接解密DES密文字符串的方法啊, 他的整个加密/解密过程都是内部自己在玩, 解密时需要用到加密的结果对象, 这不是坑我吗?

只好研究下CryptoJS DES加密后返回的对象, 发现有一个属性ciphertext, 就是密文的WordArray, 那么解密的时候, 我们是不是只要提供这个就行了呢?
var keyHex = CryptoJS.enc.Utf8.parse('abcd1234');
// direct decrypt ciphertext
var decrypted = CryptoJS.DES.decrypt(
ciphertext: CryptoJS.enc.Base64.parse('8dKft9vkZ4I=')
, keyHex,
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
);
console.log(decrypted.toString(CryptoJS.enc.Utf8));

果不其然, 到此为止, 问题全部解决, 豁然开朗...

完整代码请参考CryptoJS-DES.html
Use CryptoJS encrypt message by DES and direct decrypt ciphertext, compatible with Java Cipher.getInstance("DES")
参考技术A 下边是DES加密的方法。将数据进行DES加密,将加密内容转为16进制内容表示。
--------------------------------------------------------------------------------------------

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class DesTest

public static void main(String[] args) throws Exception
// 要加密的数据
String str = "123456";
// 密钥
String strKey = "86337898";

SecretKeySpec key = new SecretKeySpec(strKey.getBytes(), "DES");

Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteFina = cipher.doFinal(str.getBytes());
String strFinal = byte2Hex(byteFina);
System.out.println(strFinal);

cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decByte = hex2Byte(strFinal);
byte[] result = cipher.doFinal(decByte);

System.out.println(new String(result));



public static String byte2Hex(byte[] buff)
String hs = "";
for (int i = 0; i < buff.length; i++)
String stmp = (Integer.toHexString(buff[i] & 0XFF));
if (stmp.length() == 1)
hs = hs + "0" + stmp;
else
hs = hs + stmp;

return hs;


public static byte[] hex2Byte(String str)
int len = str.length() / 2;
byte[] buff = new byte[len];
int index = 0;
for (int i = 0; i < str.length(); i += 2)
buff[index++] = (byte) Integer
.parseInt(str.substring(i, i + 2), 16);


return buff;


Java数据的简单加密 DES方式

1.数据在网络中传输时,需要进行加密处理

双方约定一个相同的key(key不在网络中进行传输,只传输加密数据),然后根据将key根据一定的DES规则转换,得到真正的key,在进行加密和解密,为了增加安全性,加密过程中再加上编码base64转换,解密时先解码base64

加密和解密的完整的代码:

package com.cmit.hall.plat.play.utils;

import java.security.GeneralSecurityException;
import java.security.Key;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;

/** 
 * 数据加密 DES方式 + Base64
 * @author sun_flower
 *
 */
public class EncryUtils {
    public static final String KEY = "gEpCIKFVdPEBJ1pM5pLSviM2Nrj5C/A4iAw8ou+jiJpnrXigolapdcJXfmh2tECyuQnaFrvZHabcdefghijklmnabcdefghijklmnabcdefghijklmnabcdefghijklmn";
    /**
     * 测试
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        Key convertSecretKey = generateSecret(KEY);
        String data = "{"code":"100","roleId":[],"userDesc":"测试","sessionId":"90EA80C89F6187BAB363C9347F759E39","roleList":[],"userName":"chenpeng","checkCode":"","token":"","password":"eFEBcXRwTW2oMFSDwGwUKQ==","createTime":"2019-05-27 15:30:14","levelId":"1","staffName":"","id":1502,"userType":"1","oldPwd":""}";
        String enStr = encodeString(convertSecretKey, data);
        decodeString(convertSecretKey, enStr);
    }
    /**
     * 转换key
     * @param key
     * @return
     * @throws GeneralSecurityException
     */
    public static Key generateSecret(String key) throws GeneralSecurityException {
        byte[] bytesKey = key.getBytes();
        DESKeySpec desKeySpec = new DESKeySpec(bytesKey);//实例化DESKey秘钥的相关内容
        SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");//实例一个秘钥工厂,指定加密方式
        Key convertSecretKey = factory.generateSecret(desKeySpec);
        return convertSecretKey;
    }
    /**
     * 加密
     * @param convertSecretKey
     * @param date
     * @return
     * @throws GeneralSecurityException
     */
    public static String encodeString(Key convertSecretKey, String data) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//通过Cipher这个类进行加解密相关操作
        cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
        byte[] enData = Base64.getEncoder().encode(data.getBytes());
        byte[] result = cipher.doFinal(enData);//输入要加密的内容
        System.out.println("加密的结果:" + Hex.encodeHexString(result));
        return Hex.encodeHexString(result);
        
    }
    
    /**
     * 解密
     * @param convertSecretKey
     * @param date
     * @return
     * @throws GeneralSecurityException
     * @throws DecoderException 
     */
    public static String decodeString(Key convertSecretKey, String data) throws GeneralSecurityException, DecoderException {
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");//通过Cipher这个类进行加解密相关操作
        cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
        byte[] hdata = Hex.decodeHex(data.toCharArray());
        byte[] result = cipher.doFinal(hdata);
        byte[] decode = Base64.getDecoder().decode(result);
        System.out.println("解密结果:" + new String(decode));
        return new String(decode);
    }
    
    
    
    
}

以上是关于怎么把mysql数据库中现有的数据进行des加密,加密后的结果和java中des加密的结果一样。的主要内容,如果未能解决你的问题,请参考以下文章

java进行3des加密传过来的数据,php怎么解密?

php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密

MS SQL DES数据加密 解密,急求各位大虾帮帮小弟!

连接到 IDE 中现有的 hsqldb 实例

DES算法详解

java 实现 DES加密 解密算法