JAVA字符串加密解密

 

需求:

对给定的一串字符串进行加密解密,先用如下方式进行尝试

//密钥
private static final String encryptionKey = "SecretKey9970408";
//加解密算法/工作模式/填充方式
private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";

private static byte[] encrypt(String plainText) throws Exception {
    SecretKeySpec key = new SecretKeySpec(EncryptUtils.encryptionKey.getBytes(StandardCharsets.UTF_8), "AES");
    Cipher cipher = Cipher.getInstance(EncryptUtils.ALGORITHM_STR);
    cipher.init(Cipher.ENCRYPT_MODE, key);
    return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
}

问题:

给定的字符串有时只是改动一小部分,比如100个字符串,只改动最后2个,这导致生成的加密后字符串也是,前面大段相同的,只有一小部分不同,这样容易被看出规律。

解决:

思路是每次需要加密的字符串都可能只改动一小部分,就抓住这改动的小部分,放大扰动。

具体的做法是:计算待加密字符串每个字符的char值并求和,再将求到的和除以10并取余得到偏移量,将原字符串的每个字符的char值加上这个偏移量得到一个新的字符串,再将新的字符串按上面的方式再进行加密。以此来实现待加密字符串只改动了一小点,生成的加密后字符串改动很多,最终达到难找出规律的目的。

package lcfc.cloud.common.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class EncryptUtils {

    //生成偏移量
    private static int calcOffset(String s) {
        int sum = 0;
        for (int i = 0; i < s.length(); i++) {
            sum += s.charAt(i);
        }
        return sum % 10;
    }

    //加上偏移量
    private static String addOffset(String plaintext, int offset) {

        // 将字符串转换为字符数组
        char[] charArray = plaintext.toCharArray();

        // 对每个字符进行偏移
        for (int i = 0; i < charArray.length; i++) {
            charArray[i] = (char)(charArray[i] + offset);
        }

        // 将字符数组转换回字符串
        return offset + ";" + new String(charArray);
    }

    //减去偏移量
    private static String minusOffset(String ciphertext, int offset) {

        ciphertext = ciphertext.substring(2);

        // 将字符串转换为字符数组
        char[] charArray = ciphertext.toCharArray();

        // 对每个字符进行偏移
        for (int i = 0; i < charArray.length; i++) {
            charArray[i] = (char)(charArray[i] - offset);
        }

        // 将字符数组转换回字符串
        return new String(charArray);
    }

    //密钥
    private static final String encryptionKey = "SecretKey9970408";
    //加解密算法/工作模式/填充方式
    private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";

    private static byte[] encrypt(String plainText) throws Exception {
        SecretKeySpec key = new SecretKeySpec(EncryptUtils.encryptionKey.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher = Cipher.getInstance(EncryptUtils.ALGORITHM_STR);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
    }

    private static String decrypt(byte[] cipherText) throws Exception {
        SecretKeySpec key = new SecretKeySpec(EncryptUtils.encryptionKey.getBytes(StandardCharsets.UTF_8), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return new String(cipher.doFinal(cipherText), StandardCharsets.UTF_8);
    }

    // 加密 AES+偏移量
    public static String encryptWithOffset(String plainText) throws Exception {
        int offset = calcOffset(plainText);
        String addCode = addOffset(plainText, offset);
        byte[] cipherText = encrypt(addCode);
        return Base64.getEncoder().encodeToString(cipherText);
    }

    // 解密 AES-偏移量
    public static String decryptWithOffset(String cipherText) throws Exception {
        byte[] cipherTextB = Base64.getDecoder().decode(cipherText);
        String decryptedText = decrypt(cipherTextB);
        return minusOffset(decryptedText, Integer.parseInt(decryptedText.substring(0,1)));
    }

    //调试用
    public static void main(String[] args) throws Exception {

        String content = "ABC;" +
                "1420930972299227138,1420930972299227138,1420930972299227138,1420930972299227138,1420930972299227138," +
                "1420930972299227138,1420930972299227138,1420930972299227138,1420930972299227138,1420930972299227138" +
                "|M12;" +
                System.currentTimeMillis();
        int offset = calcOffset(content);
        System.out.println("偏移量:" + offset);
        System.out.println("原始字符串:" + content);

        String addCode = addOffset(content, offset);
        System.out.println("偏移后原始字符串:" + addCode);


        byte[] cipherText = encrypt(addCode);
        System.out.println("加密后字符串: " + Base64.getEncoder().encodeToString(cipherText));

        String decryptedText = decrypt(cipherText);
        System.out.println("解密后字符串: " + decryptedText);

        String decode = minusOffset(decryptedText, Integer.parseInt(decryptedText.substring(0,1)));
        System.out.println("偏移后解密字符串:" + decode);

    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值