首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用3 3DES限制加密数据的大小

使用3 3DES限制加密数据的大小
EN

Stack Overflow用户
提问于 2022-07-18 19:06:09
回答 1查看 146关注 0票数 0

我正试图使用3 3DES加密和解密一串数据,它工作得很好。但是,我希望加密后的数据大小限制在16位的长度之内。

这是我从https://gist.github.com/riversun/6e15306cd6e3b1b37687a0e5cec1cef1引用的代码:

代码语言:javascript
复制
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class DesedeCrypter {

private static final String CRYPT_ALGORITHM = "DESede";
private static final String PADDING = "DESede/CBC/NoPadding";
private static final String CHAR_ENCODING = "UTF-8";

private static final byte[] MY_KEY = "5oquil2oo2vb63e8ionujny6".getBytes();//24-byte
private static final byte[] MY_IV = "3oco1v52".getBytes();//8-byte

public static void main(String[] args) {

    String srcText = "M3A1B2C3D4HHG393";

    final DesedeCrypter crypter = new DesedeCrypter();

    String encryptedText = crypter.encrypt(srcText);

    System.out.println("sourceText=" + srcText + " -> encryptedText=" + encryptedText + "\n");

    System.out.println("encrypted-text=" + encryptedText + " -> decrypted-text(source text)="
            + crypter.decrypt(encryptedText));
}

public String encrypt(String text) {

    String retVal = null;

    try {

        final SecretKeySpec secretKeySpec = new SecretKeySpec(MY_KEY, CRYPT_ALGORITHM);

        final IvParameterSpec iv = new IvParameterSpec(MY_IV);

        final Cipher cipher = Cipher.getInstance(PADDING);

        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);

        final byte[] encrypted = cipher.doFinal(text.getBytes(CHAR_ENCODING));

        retVal = new String(encodeHex(encrypted));

    } catch (Exception e) {
        e.printStackTrace();
    }
    return retVal;
}

public String decrypt(String text) {

    String retVal = null;
    try {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(MY_KEY, CRYPT_ALGORITHM);
        final IvParameterSpec iv = new IvParameterSpec(MY_IV);

        final Cipher cipher = Cipher.getInstance(PADDING);

        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, iv);

        final byte[] decrypted = cipher.doFinal(decodeHex(text.toCharArray()));

        retVal = new String(decrypted, CHAR_ENCODING);

    } catch (Exception e) {
        e.printStackTrace();
    }
    return retVal;
}

private byte[] decodeHex(char[] data) throws Exception {

    int len = data.length;
    if ((len & 0x01) != 0) {
        throw new Exception("Odd number of characters.");
    }
    byte[] out = new byte[len >> 1];

    // two characters form the hex value.
    for (int i = 0, j = 0; j < len; i++) {

        int f = toDigit(data[j], j) << 4;
        j++;
        f = f | toDigit(data[j], j);
        j++;
        out[i] = (byte) (f & 0xFF);
    }
    return out;
}

private int toDigit(char ch, int index) throws Exception {
    int digit = Character.digit(ch, 16);
    if (digit == -1) {
        throw new Exception("Illegal hexadecimal character " + ch + " at index " + index);
    }
    return digit;
}

private char[] encodeHex(byte[] data) {

    final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    int l = data.length;
    char[] out = new char[l << 1];
    // two characters form the hex value.
    for (int i = 0, j = 0; i < l; i++) {
        out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
        out[j++] = DIGITS[0x0F & data[i]];
    }
    return out;
}
}

目前,这是我正在获得的输出:

代码语言:javascript
复制
sourceText=M3A1B2C3D4HHG393 -> encryptedText=afc1d48ea5cc703253cbc1a88a198103

encrypted-text=afc1d48ea5cc703253cbc1a88a198103 -> decrypted-text(source text)=M3A1B2C3D4HHG393

有没有办法将encryptedText的大小限制在16,因为我想将加密的文本添加回一条消息中,该消息有16位的加密文本空间。

请提出实现这一目标所需的某些方式或任何其他更改。谢谢!

EN

回答 1

Stack Overflow用户

发布于 2022-07-18 21:25:07

首先,我强烈建议不再支持(3)DES,因为它是赞成AES/ChaCha的官方不安全,在回答这个问题之前我必须这样说。

3 3DES的块大小为64位(或8字节)。随之而来的还有加密≠压缩。因此,如果要加密16字节,请提供16字节的输入,除非:

  1. 您应用了一个填充方案(看起来您没有这样做)(取自DESede/CBC/NoPadding )
  2. 你应用一个(随机)初始化向量(它看起来你在做)

后者应该会创建一个64位(8字节) iv,因为iv应该和密码的块大小一样大(同样,3 3DES的64位)。

因此,如果您想要16字节的输出,您可以而且应该只提供8个字节进行加密。现在,如果8个字节不够,您可以选择将iv从密文中删除,如果使用固定的iv (例如所有为零的iv)和随机密钥,就可以这样做,因为对iv重复使用相同的密钥是不安全的。

现在,如果考虑到安全性,请记住AES的块大小为16字节。AES和ChaCha对于iv具有相同的约束。

然后,您可能还需要考虑更改消息(协议),这样它就可以占用超过16个字节的数据,或者使用这16个字节的方式来表示有更多的数据需要处理,就像电子邮件的附件一样。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73027395

复制
相关文章

相似问题

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