简体   繁体   English

为什么在加密的base64编码字符串中添加字符不会破坏解密?

[英]Why does adding a character to an encrypted base64 encoded string NOT break the decryption?

I have java code using aes algorithm. 我有使用aes算法的java代码。 It can encrypt and decrypt strings properly. 它可以正确地加密和解密字符串。 However what we found that, if I add a (only one) character to the end of encrypted string, I can still decrypt it to correct plain text value. 然而,我们发现,如果我在加密字符串的末尾添加一个(只有一个)字符,我仍然可以解密它以纠正纯文本值。 If I append 2 or more, it can't decrypt. 如果我追加2或更多,则无法解密。

I tried des and other alogorithm and still the same behavior. 我试过des和其他alogorithm仍然是相同的行为。 I also tried padding etc, no luck 我也试过填充等,没有运气

Is that normal behavior? 这是正常的行为吗? How I can get around it? 我怎么能绕过它?

Thanks 谢谢

M 中号

public class testCipher 
{
    public static final String PROVIDER = "SunJCE";
    private static final String ALGORITHM = "AES";
    private static final String aesKey = "some long key";
    static Cipher ecipher;
    static Cipher dcipher;

    public static void main(String[] args)  
    {

    try {

    byte[] buf1 = aesKey.getBytes("UTF-8");
    MessageDigest sha = MessageDigest.getInstance("SHA-256");
    buf1 = sha.digest(buf1);
    buf1 = Arrays.copyOf(buf1, 16);
    SecretKeySpec keySpec = null;
    keySpec = new SecretKeySpec(buf1, "AES");

    ecipher = Cipher.getInstance(ALGORITHM, PROVIDER);
    dcipher = Cipher.getInstance(ALGORITHM, PROVIDER);

    ecipher.init(1, keySpec);
    dcipher.init(2, keySpec, ecipher.getParameters());

    if (args[0].equals("encrypt"))
    System.out.println(encrypt(args[1]));
    else if (args[0].equals("decrypt"))
    System.out.println(decrypt(args[1]));
    else {
    System.out.println("USAGE: encrypt/decrypt '<string>'");
    System.exit(15);
   }

} catch (Exception e) {
    System.exit(5);
} 

}

public static String encrypt(String str) 
{
    try {

        byte[] utf8 = str.getBytes("UTF8");
        byte[] enc = ecipher.doFinal(utf8);
        return new sun.misc.BASE64Encoder().encode(enc);

    } catch (Exception e) {
        System.exit(7);
    }

    return null;
}

public static String decrypt(String str) 
{
    try {
        // Decode base64 to get bytes
        byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);

        // Decrypt
        byte[] utf8 = dcipher.doFinal(dec);

        // Decode using utf-8
        return new String(utf8, "UTF8");
    } catch (Exception e) {
        System.exit(7);
    } 
    return null;
}
}

It's impossible to answer properly without some sort of source code to indicate what exactly you're doing, but there are a number of possibilities, mostly related to encoding sizes. 如果没有某种源代码来指示你究竟在做什么,就不可能正确回答,但是有很多可能性,主要与编码大小有关。

Encoding and encryption typically blocks sizes. 编码和加密通常会阻止大小。 For instance, hex encoding of a set of bytes requires two output bytes for every one input byte. 例如,一组字节的十六进制编码对于每一个输入字节需要两个输出字节。 Base 64 encoding uses 5 output bytes for every 4 input bytes. Base 64编码每4个输入字节使用5个输出字节。 Most encryption algorithms work in 64 or 128 bit blocks, ie 8 or 16 bytes. 大多数加密算法工作在64或128位块,即8或16字节。

If you're fiddling with an encoded string and add only a single character to it, it's possible (again, impossible to say for sure without source code) that you're adding insufficient information for the additional character to be treated as a block in whatever processing it's undergoing, and so it sounds like it's being silently ignored. 如果你正在摆弄一个编码的字符串并且只添加一个字符,那么你可能会在没有源代码的情况下再次确定你要添加的信息不足以将其他字符视为一个块。无论它正在经历什么样的处理,所以听起来它被默默地忽略了。 Adding two character crashes, so that's probably pushing you over some limit. 添加两个角色崩溃,这可能会推动你超过一些限制。

As blorgbeard points out in the comments, a) why do you care and b) why are you fiddling with encrypted strings in the first place? 正如blorgbeard在评论中指出的那样,a)你为什么关心和b)你为什么要首先摆弄加密的字符串?

EDIT: 编辑:

Based on your code it's exactly what I said. 根据你的代码,这正是我所说的。 It has nothing to do with the encryption, and everything to do with the Base64 encoding you're using. 它与加密无关,而与您正在使用的Base64编码有关。

    String str = "foo";
    String enc = new sun.misc.BASE64Encoder().encode(str.getBytes(Charsets.UTF_8));
    // enc = enc + "x";
    // enc = enc + "x";
    byte [] decBytes = new sun.misc.BASE64Decoder().decodeBuffer(enc);
    String dec = new String(decBytes, Charsets.UTF_8);
    System.out.println(dec);

If you comment out one of those enc = enc + "X"; 如果你注释掉其中一个enc = enc + "X"; lines, the program will still print 'foo', but if you comment out two of them, then it will print foo + some garbage characters afterwards. 行,程序仍将打印'foo',但如果你注释掉其中两个,那么之后会打印foo +一些乱码。 This is because a single character of Base64 encoded data is meaningless. 这是因为Base64编码数据的单个字符没有意义。 It requires at least two characters to encode a single byte in Base64, so that's why the first character is ignored and the second causes problems. 它需要至少两个字符来编码Base64中的单个字节,这就是为什么忽略第一个字符而第二个字符导致问题的原因。

However, going back to the root of the problem, your comments suggests that users might be able to edit these values? 但是,回到问题的根源,您的评论表明用户可能能够编辑这些值? That's.... well, that's insane. 那是......好吧,那太疯狂了。 You don't ever provide any functionality for modifying encrypted data except to move it from one location to another, or to encrypt or decrypt data. 除了将加密数据从一个位置移动到另一个位置,或加密或解密数据外,您不会提供任何修改加密数据的功能。

Also, you shouldn't really be using any of the classes in sun.misc package. 此外,您不应该真正使用sun.misc包中的任何类。 sun.misc is considered internal to Java, and using it means there's no guarantees that it will work in a given fashion, or that it will exist from one JVM to another. sun.misc被认为是Java的内部,使用它意味着不能保证它将以给定的方式工作,或者它将从一个JVM存在到另一个JVM。 There are open source libraries out that do Base64 transcoding (Apache Commons-Codec is popular) and you should be using one of those. 有一些开源库可以进行Base64转码(Apache Commons-Codec很受欢迎),你应该使用其中一种。 Using undocumented features inside the JVM could easily be considered your main problem. 在JVM中使用未记录的功能很容易被认为是您的主要问题。 I haven't checked the docs on Commons-Codec, but it's possible that it will throw an exception if it encounters an unexpected number of input bytes for decoding. 我没有检查Commons-Codec上的文档,但如果遇到意外数量的输入字节进行解码,它可能会抛出异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM