解码UTF-8字符串

时间:2016-01-16 03:23:30

标签: java encryption utf-8

import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class CryptoLib {

    public CryptoLib() {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
    }

    public String encrypt(String plainText, String key) throws Exception {

        // convert key to bytes
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(key.getBytes("UTF-8"));

        byte[] keyBytes = md.digest();

        // Use the first 16 bytes (or even less if key is shorter)
        byte[] keyBytes16 = new byte[16];
        System.arraycopy(keyBytes, 0, keyBytes16, 0, Math.min(keyBytes.length, 64));

        System.arraycopy(keyBytes, 0, keyBytes16, 0,
                Math.min(keyBytes.length, 16));

        // convert plain text to bytes
        byte[] plainBytes = plainText.getBytes("UTF-8");

        // setup cipher
        SecretKeySpec skeySpec = new SecretKeySpec(keyBytes16, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        byte[] iv = new byte[16]; // initialization vector with all 0
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));

        // encrypt
        byte[] encrypted = cipher.doFinal(plainBytes);
        String encryptedString = new String(Base64.encodeBase64(cipher.doFinal(encrypted)));
        // encryptedString

        return encryptedString;
    }

    public String Decrypt(String EncryptedText, String key) throws Exception {
        // convert key to bytes
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(key.getBytes("UTF-8"));

        byte[] keyBytes = md.digest();
        // Use the first 16 bytes (or even less if key is shorter)
        byte[] keyBytes16 = new byte[16];

        System.arraycopy(keyBytes, 0, keyBytes16, 0, Math.min(keyBytes.length, 64));

        // convert plain text to bytes
        //  byte[] decodeBase64 = Base64.decodeBase64(EncryptedText);
        byte[] plainBytes = Base64.decodeBase64(EncryptedText.getBytes("UTF-8"));

        // setup cipher
        SecretKeySpec skeySpec = new SecretKeySpec(keyBytes16, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        byte[] iv = new byte[16]; // initialization vector with all 0
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(iv));


        byte[] decrypteed = cipher.doFinal(plainBytes);


        return new String(decrypteed, "UTF-8");
    }
}

大家好,很抱歉这个愚蠢的问题,但我有一个小问题,我无法找到解决方案。我成功加密和解密一条消息,但是他们解密函数返回奇怪的字符串,虽然我设置了utf8格式。输出在下面

run:
Yv6GgSE2H19kqP/fH8qnl7HDJ5zM2DlPrNYT6d4YCII=
���`�1����X��
BUILD SUCCESSFUL (total time: 0 seconds)


CryptoLib crypto=new CryptoLib();
String encrypted=crypto.encrypt("Message", "key");
System.out.println(encrypted);
System.out.println(crypto.Decrypt(encrypted, "key"));

1 个答案:

答案 0 :(得分:1)

有以下几行的双重加密:

byte[] encrypted = cipher.doFinal(plainBytes);
String encryptedString = new String(Base64.encodeBase64(cipher.doFinal(encrypted)));

这也解释了加密数据的额外长度,

  

Base64:Yv6GgSE2H19kqP / fH8qnl7HDJ5zM2DlPrNYT6d4YCII =
  十六进制:62FE868121361F5F64A8FFDF1FCAA797B1C3279CCCD8394FACD613E9DE180882

加密应该只是:

String encryptedString = new String(Base64.encodeBase64(cipher.doFinal(plainBytes)));

这就是为什么解密是“奇怪的”,它是二进制数据字节显示为一个字符串,它不具有不可显示的字节。