我正试图使用3 3DES加密和解密一串数据,它工作得很好。但是,我希望加密后的数据大小限制在16位的长度之内。
这是我从https://gist.github.com/riversun/6e15306cd6e3b1b37687a0e5cec1cef1引用的代码:
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;
}
}目前,这是我正在获得的输出:
sourceText=M3A1B2C3D4HHG393 -> encryptedText=afc1d48ea5cc703253cbc1a88a198103
encrypted-text=afc1d48ea5cc703253cbc1a88a198103 -> decrypted-text(source text)=M3A1B2C3D4HHG393有没有办法将encryptedText的大小限制在16,因为我想将加密的文本添加回一条消息中,该消息有16位的加密文本空间。
请提出实现这一目标所需的某些方式或任何其他更改。谢谢!
发布于 2022-07-18 21:25:07
首先,我强烈建议不再支持(3)DES,因为它是赞成AES/ChaCha的官方不安全,在回答这个问题之前我必须这样说。
3 3DES的块大小为64位(或8字节)。随之而来的还有加密≠压缩。因此,如果要加密16字节,请提供16字节的输入,除非:
DESede/CBC/NoPadding )后者应该会创建一个64位(8字节) iv,因为iv应该和密码的块大小一样大(同样,3 3DES的64位)。
因此,如果您想要16字节的输出,您可以而且应该只提供8个字节进行加密。现在,如果8个字节不够,您可以选择将iv从密文中删除,如果使用固定的iv (例如所有为零的iv)和随机密钥,就可以这样做,因为对iv重复使用相同的密钥是不安全的。
现在,如果考虑到安全性,请记住AES的块大小为16字节。AES和ChaCha对于iv具有相同的约束。
然后,您可能还需要考虑更改消息(协议),这样它就可以占用超过16个字节的数据,或者使用这16个字节的方式来表示有更多的数据需要处理,就像电子邮件的附件一样。
https://stackoverflow.com/questions/73027395
复制相似问题