解密在正式版(Red Hat Enterprise Linux 7)上不起作用,而在UAT(基于SUSE的Linux发行版)上起作用

时间:2019-06-27 10:36:54

标签: java linux encryption redhat des

我不建议使用DES进行加密/解密,因为它是旧代码,所以我无法使用AES,现在我的代码可以在具有生产db的本地环境(即mac)上正常工作,也可以正常工作在基于SUSE的Linux发行版的UAT上运行,但是解密在基于Redhat的生产环境下无法正常工作。生产时会抛出“输入长度(带填充)不是8个字节的倍数”的非法块大小异常

@Service
public class EncryptionUtil {

    private static final Logger log = LogManager.getLogger(EncryptionUtil.class);
    @Autowired
    GpsCacheManager gpsCacheManager;
    private Cipher ecipher;
    private Cipher dcipher;
    @Autowired
    private StringUtils stringUtils;

    public EncryptionUtil() throws Exception {
        ecipher = Cipher.getInstance("DES");
        dcipher = Cipher.getInstance("DES");
        initCipher();
    }


    private void initCipher() {
        try {
            String response = “[-3232, -34, -98, 111, -222, 33, -22, 55]”;
            String[] byteValues = response.substring(1, response.length() - 1).split(",");
            byte[] bytes = new byte[byteValues.length];
            for (int i = 0, len = bytes.length; i < len; i++) {
                bytes[i] = Byte.parseByte(byteValues[i].trim());
            }

            SecretKey key = new SecretKeySpec(bytes, "DES");
            ecipher.init(Cipher.ENCRYPT_MODE, key);
            dcipher.init(Cipher.DECRYPT_MODE, key);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }


    public String encryptUTF8(String str) throws Exception {
        // Encode the string into bytes using utf-8
        byte[] utf8 = str.getBytes("UTF8");

        // Encrypt
        byte[] enc = ecipher.doFinal(utf8);
        // Encode bytes to base64 to get a string
        return new String(Base64.encodeBase64(enc));
    }

    public String decryptUTF8(String str) throws Exception {

        if (stringUtils == null) {
            stringUtils = new StringUtils();
        }
        //do not decrypt if a valid email.
        if (stringUtils.isValidEmail(str)) {
            return str;
        }
        // Decode base64 to get bytes
        byte[] dec = Base64.decodeBase64(str.getBytes());

        byte[] utf8 = null;
        try {
            utf8 = dcipher.doFinal(dec);
        } catch (IllegalBlockSizeException e) {
            return str;
        }
        // Decode using utf-8
        return new String(utf8, "UTF8");
    }
}

1 个答案:

答案 0 :(得分:1)

String.getBytes()new String(byte[])存在问题,它们与平台有关,因此不应在此处使用。同时,我用标准Java的Base64替换了Base64类,该类旨在替代十年前的几种Base64实现。

public String encryptUTF8(String str) throws Exception {
    // Encode the string into bytes using utf-8
    byte[] utf8 = str.getBytes(StandardCharsets.UTF_8);

    // Encrypt
    byte[] enc = ecipher.doFinal(utf8);
    // Encode bytes to base64 to get a string
    return Base64.getEncoder().encodeToString(enc));
    //Old class: return new String(Base64.encodeBase64(enc), StandardCharsets.US_ASCII);
}

public String decryptUTF8(String str) throws Exception {

     if (stringUtils == null) {
            stringUtils = new StringUtils();
     }
     //do not decrypt if a valid email.
     if (stringUtils.isValidEmail(str)) {
        return str;
     }
     // Decode base64 to get bytes
     //byte[] dec = Base64.getDecoder().decode(str.getBytes(StandardCharsets.US_ASCII));    
     byte[] dec = Base64.getDecoder().decode(str);    
     try {
         byte[] utf8 = dcipher.doFinal(dec);
         // Decode using utf-8
         return new String(utf8, StandardCharsets.UTF_8);
     } catch (IllegalBlockSizeException e) {
         return str;
     }
}

有一个问题:String用于Unicode文本,带有两个字节的char(UTF-16)。 这意味着任何byte[]值都必须是某种编码的文本,并且该编码必须转换为字符串。任何任意byte[]值都不是有效的字符串。尤其是在具有卓越的UTF-8编码的Linux上,它将破坏数据。

问题可能出在decryptUTF8。如果在原始代码中默认编码为单字节编码,则所有内容均被原样吞下。对于Linux,UTF-8可能会遇到错误的UTF-8多字节序列。 或者编码是7位ASCII。

通常将Stringbyte[]分开;将byte[]用于非文本二进制数据。