简体   繁体   English

如何在java中实现双鱼加密来加密/解密字符串?

[英]How to implement twofish encryption to encrypt/decrypt strings in java?

i recently downloaded twofish-java.zip from https://www.schneier.com/academic/twofish/download.html .我最近从https://www.schneier.com/academic/twofish/download.html下载了 twofish-java.zip。 There is a jar file inside it twofish.jar.里面有一个 jar 文件 twofish.jar。 Some one explain me how to implement twofish encryption in java to encrypt/decrypt strings in java using this jar file有人向我解释了如何在 Java 中实现双鱼加密以使用此 jar 文件在 Java 中加密/解密字符串

You need to implement the functions blockEncrypt() and blockDecrypt() and build an mode of operation around them.您需要实现函数blockEncrypt()blockDecrypt()并围绕它们构建一种操作模式。 Keys are created with the makeKey() function, which requires a key length of 8, 16, 24 or 32 bytes.密钥是使用makeKey()函数创建的,该函数需要 8、16、24 或 32 个字节的密钥长度。 Make sure that the plaintext is padded to a multiple of 16 bytes.确保将明文填充为 16 字节的倍数。 I have attached my code for ECB and CBC mode with Twofish.我已经附上了我的带有 Twofish 的 ECB 和 CBC 模式的代码。 I would recommend you to implement your own padding function and key expansion function if you want the best security.如果您想要最好的安全性,我建议您实现自己的填充功能和密钥扩展功能。 In my example, the same key is used for each block and the plaintext is only padded with 0 at the end.在我的示例中,每个块都使用相同的密钥,并且明文仅在末尾填充 0。

static byte[] ecbEncrypt(byte[] plaintext, byte[] key) throws InvalidKeyException {
    byte[] pt = pad(plaintext, 16);
    byte[] ciphertext = new byte[pt.length];
    for (int i = 0; i < pt.length; i += 16) {
        byte[] t = Twofish_Algorithm.blockEncrypt(pt, i, Twofish_Algorithm.makeKey(key));
        for (int j = i; j < i + 16; j++) 
            ciphertext[j] = t[j % 16];
    }
    return ciphertext;
}

static byte[] ecbDecrypt(byte[] ciphertext, byte[] key) throws InvalidKeyException {
    byte[] plaintext = new byte[ciphertext.length];
    for (int i = 0; i < ciphertext.length; i += 16) {
        byte[] t = Twofish_Algorithm.blockDecrypt(ciphertext, i, Twofish_Algorithm.makeKey(key));
        for (int j = i; j < i + 16; j++) 
            plaintext[j] = t[j % 16];
    }
    return unpad(plaintext);
}
static byte[] cbcEncrypt(byte[] plaintext, byte[] key, byte[] iv) throws InvalidKeyException {
    byte[] pt = pad(plaintext, 16);
    byte[] ciphertext = new byte[pt.length];
    for (int i = 0; i < 16; i++)
        pt[i] ^= iv[i];
    byte[] t = Twofish_Algorithm.blockEncrypt(pt, 0, Twofish_Algorithm.makeKey(key));
    for (int i = 0; i < 16; i++)
        ciphertext[i] = t[i];
    for (int i = 16; i < pt.length; i += 16) {
        for (int j = 0; j < 16; j++)
            pt[i + j] ^= ciphertext[i - 16 + j];
        byte[] t2 = Twofish_Algorithm.blockEncrypt(pt, i, Twofish_Algorithm.makeKey(key));
        for (int j = 0; j < 16; j++)
            ciphertext[i + j] = t2[j];
    }
    return ciphertext;
}

static byte[] cbcDecrypt(byte[] ciphertext, byte[] key, byte[] iv) throws InvalidKeyException {
    byte[] plaintext = new byte[ciphertext.length];
    byte[] t = Twofish_Algorithm.blockDecrypt(ciphertext, 0, Twofish_Algorithm.makeKey(key));
    for (int i = 0; i < 16; i++) 
        plaintext[i] = (byte) (t[i] ^ iv[i]);
    for (int i = 16; i < ciphertext.length; i += 16) {
        byte[] t2 = Twofish_Algorithm.blockDecrypt(ciphertext, i, Twofish_Algorithm.makeKey(key));
        for (int j = 0; j < 16; j++)
            plaintext[i + j] = (byte) (t2[j] ^ ciphertext[i - 16 + j]);
    }
    return unpad(plaintext);
}
static byte[] pad(byte[] in, int blockSize) {
    byte[] ret = new byte[in.length + blockSize - in.length % blockSize];
    for (int i = 0; i < in.length; i++) 
        ret[i] = in[i];
    byte paddedBytes = 0;
    for (int i = in.length; i < ret.length - 1; i++) {
        ret[i] = 0;
        paddedBytes++;
    }
    ret[ret.length - 1] = paddedBytes;
    return ret;
}

static byte[] unpad(byte[] in) {
    byte[] ret = new byte[in.length - in[in.length - 1] - 1];
    for (int i = 0; i < ret.length; i++) 
        ret[i] = in[i];
    return ret;
}

This implementation is probably not going to be perfect, so feel free to write me improvements so I can edit my response.这个实现可能不会是完美的,所以请随时给我写改进,以便我可以编辑我的回复。

You can call the functions like this:您可以像这样调用函数:

SecureRandom sr = new SecureRandom();

byte[] plaintext = "This is secret plaintext".getBytes();
byte[] key = new byte[16];
byte[] iv = new byte[16];
sr.nextBytes(key);
sr.nextBytes(iv);

System.out.println("Plaintext: " + new String(plaintext));
byte[] ecbCiphertext = ecbEncrypt(plaintext, key);
System.out.println("ECB-Ciphertext: " + new String(ecbCiphertext));
byte[] ecbPlaintext = ecbDecrypt(ecbCiphertext, key);
System.out.println("ECB-Plaintext: " + new String(ecbPlaintext));
byte[] cbcCiphertext = cbcEncrypt(plaintext, key, iv);
System.out.println("CBC-Ciphertext: " + new String(cbcCiphertext));
byte[] cbcPlaintext = cbcDecrypt(cbcCiphertext, key, iv);
System.out.println("CBC-Plaintext: " + new String(cbcPlaintext));
Plaintext: This is secret plaintext
ECB-Ciphertext: ÑìÔõ¬ŽÁ@γ÷ÊÑ–1—N,/ )ë+$
ECB-Plaintext: This is secret plaintext
CBC-Ciphertext: JÉÌÙ•=Hæí_•¤iÔ[%˜Å?ÆÍæ“!Ø?%
CBC-Plaintext: This is secret plaintext

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

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