首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在java中实现双重加密以加密/解密字符串?

如何在java中实现双重加密以加密/解密字符串?
EN

Stack Overflow用户
提问于 2017-09-25 03:44:39
回答 1查看 1.3K关注 0票数 3

我最近从https://www.schneier.com/academic/twofish/download.html下载了twofish-java.zip。twofish.jar中有一个jar文件。有些人解释了如何在java中实现双重加密,以便使用这个jar文件在java中加密/解密字符串。

EN

回答 1

Stack Overflow用户

发布于 2021-12-11 11:55:52

您需要实现blockEncrypt()blockDecrypt()函数,并围绕它们构建一种操作模式。键是用makeKey()函数创建的,它要求密钥长度为8、16、24或32字节。确保明文被填充到16个字节的倍数中。我已经用Twofish附加了欧洲央行和CBC模式的代码。如果您想获得最好的安全性,我建议您实现自己的填充函数和键扩展功能。在我的示例中,每个块都使用相同的键,明文在末尾只填充0。

代码语言:javascript
复制
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);
}
代码语言:javascript
复制
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);
}
代码语言:javascript
复制
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;
}

这个实现可能不是完美的,所以可以随意编写改进,这样我就可以编辑我的响应了。

您可以这样调用这些函数:

代码语言:javascript
复制
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));
代码语言:javascript
复制
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

如果您想要一种使用计数器模式进行加密/解密的方法,我也附加了我的实现。

代码语言:javascript
复制
static byte[] ctrEncrypt(byte[] plaintext, byte[] key, byte[] iv) throws InvalidKeyException {
    byte[] initializationVector = Arrays.copyOf(iv, iv.length);
    byte[] counter = { -128, -128, -128, -128, -128, -128, -128, -128 };
    byte[] ciphertext = new byte[plaintext.length];
    for (int i = 0; i < plaintext.length / 16 + 1; i++) {
        for (int j = 0; j < 8; j++) {
            if (counter[j] == 127 && j != 7) {                  counter[j] = -128;
                counter[j + 1]++;
            }
            if (counter[j] != -128)
                initializationVector[15 - j] = counter[j];
            else
                initializationVector[15-j] = iv[15-j];
        }
        byte[] t = Twofish_Algorithm.blockEncrypt(initializationVector, 0, Twofish_Algorithm.makeKey(key));
        for (int j = 0; i < plaintext.length / 16 ? j < 16 : j < plaintext.length % 16; j++)
            ciphertext[i * 16 + j] = (byte) (plaintext[i * 16 + j] ^ t[j]);
        counter[0]++;
    }
    return ciphertext;
}

static byte[] ctrDecrypt(byte[] ciphertext, byte[] key, byte[] iv) throws InvalidKeyException {
    return ctrEncrypt(ciphertext, key, iv);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46397301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档