java - Java中的密文窃取

标签 java encryption block-cipher

所以我有一个学校项目,我遇到了一些麻烦。我们获得了加密方法,然后被要求为其创建解密方法。

public static byte[] encrypt(byte[] plaintext, BlockCipher64 cipher, long IV) {
    if(plaintext.length <= 8)
        throw new IllegalArgumentException("plaintext must be longer than 8 bytes!");

    byte[] ciphertext = new byte[plaintext.length];
    int blocks = plaintext.length / 8;
    if(plaintext.length % 8 != 0) ++blocks;

    long prev = IV;
    for(int block = 0; block < blocks; ++block) {
        prev = cipher.encrypt(prev ^ longAt(plaintext, block * 8));
        storeLongAt(ciphertext, prev, block * 8);
    }

    // copy penultimate to last, then prev to penultimate (ciphertext stealing)
    int lastBlock = (blocks - 1) * 8;
    int secondLastBlock = (blocks - 2) * 8;
    storeLongAt(ciphertext, longAt(ciphertext, secondLastBlock), lastBlock);
    storeLongAt(ciphertext, prev, secondLastBlock);

    return ciphertext;
}

因此,当字符串长度恰好为 16(2 个 block )时,我已经获得了解密方法。其他带有偶数 block (8 的倍数)的字符串不起作用,24、32 等。部分块也不起作用;如果我加密长度为18的字符串并再次解密,最后2个字符总是错误的。任何帮助深表感谢!这是我的解密方法:

public static byte[] decrypt(byte[] ciphertext, BlockCipher64 cipher, long IV) {
    // code here
    // check for an illegal argument
    if(ciphertext.length <= 8)
        throw new IllegalArgumentException("ciphertext must be longer than 8 bytes!");

    // create a byte[] for the plaintext
    byte[] plaintext = new byte[ciphertext.length];

    // calculate how many blocks there are
    int blocks = plaintext.length / 8;
    if(plaintext.length % 8 != 0) ++blocks;

    // handle the last two blocks (which are special because of ciphertext stealing)
    int lastBlock = (blocks - 1) * 8;
    int secondLastBlock = (blocks - 2) * 8;
    long lBlock = longAt(ciphertext, lastBlock);
    int lBlockSize = ciphertext.length % 8;
    // if block sizes are even; swap, if block size is partial; 
    if (lBlockSize != 0) {
        //get blocks to switch
        byte[] NLB = new byte[lBlockSize];
        for (int i=secondLastBlock, j=0; i<secondLastBlock + lBlockSize; i++, j++) {
            NLB[j] = ciphertext[i];
        }
        byte[] NSLB = new byte[lBlockSize];
        for (int i=lastBlock, j=0; i<lastBlock + lBlockSize; i++, j++) {
            NSLB[j] = ciphertext[i];
        }
        //build ciphertext
        for (int i=secondLastBlock, j=0; i<secondLastBlock + lBlockSize; i++, j++) {
            ciphertext[i] = NSLB[j];
        }
        for (int i=lastBlock, j=0; i<lastBlock + lBlockSize; i++, j++) {
            ciphertext[i] = NLB[j];
        }
    } else {
        storeLongAt(ciphertext, longAt(ciphertext, secondLastBlock), lastBlock);
        storeLongAt(ciphertext, lBlock, secondLastBlock);
    }

    // loop over all other blocks, decrypting and xor'ing, and saving the results
    long prev = IV;
    for(int block = 0; block < blocks; ++block) {
        prev = cipher.decrypt(prev ^ longAt(ciphertext, block * 8));
        storeLongAt(plaintext, prev, block * 8);
    }

    return plaintext;
}

如果需要任何其他信息,请告诉我...我真的被这个信息难住了。

编辑:其他方法和类 storeLongAt() 和 longAt():

public static void storeLongAt(byte[] b, long x, int pos) {
    byte[] c = BlockCipher64.longToBytes(x);
    for(int i = 0; i < 8 && (pos + i) < b.length; ++i) {
        b[pos + i] = c[i];
    }
}

public static long longAt(byte[] b, int pos) {
    return BlockCipher64.bytesToLong(Arrays.copyOfRange(b, pos, pos + 8));
}

BlockCipher64 类:

public interface BlockCipher64 {
long encrypt(long block);
long decrypt(long block);

public static byte[] longToBytes(long l) {
    byte[] result = new byte[8];
    for (int i = 7; i >= 0; i--) {
        result[i] = (byte) l;
        l >>= 8;
    }
    return result;
}

public static long bytesToLong(byte[] b) {
    long result = 0;
    for (int i = 0; i < 8; i++) {
        result <<= 8;
        result |= ((long) b[i]) & 0xffL; // notice the L
    }
    return result;
}
}

最佳答案

您正在交换密文字节而不是明文字节。请注意,交换发生在最后一个 block 的加密之前(及时)。如果你反转它必须在最后一个 block 解密之后交换。

当前您正在创建一个无效的密文并尝试对其进行解密。

关于java - Java中的密文窃取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38732994/

相关文章:

PHP 加密数据,Bash 解密

c - 如何破解弱化的 TEA 分组密码?

Java 加密 AES 函数

java - 需要支持 1 位反馈密码模式的 3-DES 密码库

java - 如何减少类路径中的资源加载时间?

java - 将 JVM 绑定(bind)到默认 IP 之外的 IP

c# - Azure 网站上的数据保护/加密?

java - 尝试在Unity3d中构建Android版本时遇到问题

java - 如何使用 Android NDK 创建 Java 对象(int[])

objective-c - 将 Objective-C 代码转换为 Swift