【问题标题】:Where is the IV in Triple DES?三重 DES 中的 IV 在哪里?
【发布时间】:2014-11-28 21:54:32
【问题描述】:

我正在使用三重 DES 加密数据。它工作正常,但我有一个问题。

在哪里可以看到初始化向量 (IV)?

它是带有 BASE64Decoder 的 3des 加密。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Crypter {

    Cipher ecipher;
    Cipher dcipher;

    Crypter(String as_Phrase)
            throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException {
        this.ecipher = Cipher.getInstance("DESede");
        this.dcipher = Cipher.getInstance("DESede");
        this.ecipher.init(1, getSecretKey(as_Phrase));
        this.dcipher.init(2, getSecretKey(as_Phrase));

    }

    public String encrypt(String as_valueToEncrypt)
            throws BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, IOException {
        byte[] lbarr_utf8 = as_valueToEncrypt.getBytes("UTF8");
        byte[] lbarr_enc = this.ecipher.doFinal(lbarr_utf8);

        return new BASE64Encoder().encode(lbarr_enc);
    }

    public String decrypt(String as_valueToDecrypt)
            throws BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException, IOException {
        byte[] lbarr_enc = new BASE64Decoder().decodeBuffer(as_valueToDecrypt);

        byte[] lbarr_utf8 = this.dcipher.doFinal(lbarr_enc);

        return new String(lbarr_utf8, "UTF8");
    }

    private SecretKey getSecretKey(String as_Phrase)
            throws UnsupportedEncodingException {
        return new SecretKeySpec(as_Phrase.getBytes("UTF8"), "DESede");
    }
}

【问题讨论】:

  • 您从未想过要查看 Cipher 的 Javadocs?
  • 请在上面加糖,如果已定义,请使用常量。如果没有,请定义您自己的,并在新 API 中使用枚举。 Cipher.ENCRYPT_MODEinit 方法中比1 清晰得多,你不同意吗?

标签: java encryption 3des tripledes


【解决方案1】:

您可以从密码中获取 IV:

ecipher.getIV();

问题是 IV 是在init 期间生成的。由于您在构造函数中使用init,因此您会遇到对不同密文的每次加密都使用相同 IV 的问题。最好为每个加密和解密操作单独生成一个新的Cipher 并初始化它。

您使用DESede 密码,实际上是DESede/ECB/PKCS5Padding。请注意,模式是不使用 IV 的 ECB。所以上面的调用返回null。虽然这是默认模式,但不建议这样做。使用实际使用 IV 的 DESede/CBC/PKCS5Padding 更安全。

因此,当您在 CBC 模式下解密时,您需要将 IV 传入:

dcipher.init(2, new SecretKeySpec(key, "DESede"), new IvParameterSpec(ecipher.getIV()));

为了减轻传递 IV 的负担,您可以在对密文进行编码之前将 IV 附加到密文的前面,并在解密密文之前将其切掉。 DES 是 64 位密码,因此您的 IV 长度为 8 个字节。

【讨论】:

    【解决方案2】:

    CiphergetIV() 方法,该方法返回初始化向量。

    【讨论】:

    • 这并没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post
    • @KickButtowski 这是一个答案,这个问题询问如何获得 IV,这个答案给出了一个完全可以做到这一点的方法。
    • 这是一个答案,但这不是一个好的答案,因为代码使用"DESede" 而不指定模式。在(几乎)所有运行时,这将默认为 ECB 模式,根本不使用 IV。
    • @owlstead 没错。这就是为什么我投票赞成另一个答案。但如果作者问“为什么 getIV 返回 null”,就不会发生这种情况。
    • 是的,他只是问如何获得 IV,但重要的是还要考虑问题的意图。据我所知,使用 ECB 的代码没有改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2012-03-30
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多