在Java中生成和使用两个密钥进行加密和解密

在Java中生成和使用两个密钥进行加密和解密,java,encryption,cryptography,des,Java,Encryption,Cryptography,Des,我正在开发一个Java应用程序,它需要我使用两个键 由不同的字符串生成,用于加密和解密。一 字符串来自用户,另一个是主密钥。我在网上看了看 并找到了一些关于它的参考资料。我真的想要一些 有助于了解如何实现这一点。我将展示我现在所拥有的 正如您从代码中看到的,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获得用于解密的SecretKey desKey 代码: public class Encryption {

我正在开发一个Java应用程序,它需要我使用两个键 由不同的字符串生成,用于加密和解密。一 字符串来自用户,另一个是主密钥。我在网上看了看 并找到了一些关于它的参考资料。我真的想要一些 有助于了解如何实现这一点。我将展示我现在所拥有的

正如您从代码中看到的,我使用了其他stackoverflow帖子中的一些代码,并对其进行了一些修改。我只是不知道如何从2个字符串生成2个密钥,以及从哪里可以获得用于解密的SecretKey desKey

代码:

public class Encryption {

public void doStuff() {

    String plaintext = "abc";

    SecretKey k1 = generateDESkey();
    SecretKey k2 = generateDESkey();


    String firstEncryption = desEncryption(plaintext, k1);
    String decryption = desDecryption(firstEncryption, k2);
    String secondEncryption = desEncryption(decryption, k1);

    System.out.println(firstEncryption);
    System.out.println(decryption);
    System.out.println(secondEncryption);
}

public static SecretKey generateDESkey() {
    KeyGenerator keyGen = null;
    try {
        keyGen = KeyGenerator.getInstance("DESede");
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    try {
        assert keyGen != null;
        keyGen.init(112); // key length 56
        return keyGen.generateKey();
    } catch (NullPointerException ex){
        return null;
    }
}


public static String desEncryption(String strToEncrypt, SecretKey desKey) {
    try {
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        return Base64.encode(cipher.doFinal(strToEncrypt.getBytes()));
    } catch (NoSuchAlgorithmException | NoSuchPaddingException |
            IllegalBlockSizeException | BadPaddingException |
            InvalidKeyException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}


public static String desDecryption(String strToDecrypt, SecretKey desKey) {
    try {
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        return new String(cipher.doFinal(Base64.decode(strToDecrypt)));

    } catch (NoSuchAlgorithmException |  BadPaddingException | IllegalBlockSizeException
            | InvalidKeyException | NoSuchPaddingException ex) {
        Logger.getLogger(Test.class
                .getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}

}
如果对此有任何困惑或怀疑。请让我知道。

在代码更改之前请回答

你想用两把钥匙而不是三把钥匙来做德塞德

这通常可能有效,但不像你写的那样。问题是填充物。在第二步中,您尝试使用加密密钥以外的其他密钥对密文进行解密,因此解密失败的次数将超过256次中的255次,因为填充也将是错误的,因为您在不需要的情况下使用Base64编码

如果你真的想这样做,你将不得不在没有填充和Base64编码的情况下解密。好的方面是,未编码的密文已经是blocksize的倍数,因此没有什么可以阻止您使用DES/ECB/NoPadding

当通用密钥以这种方式构造时,这实际上是具有两个密钥的DESede的等效实现:

SecretKey k1 = generateDESkey();
SecretKey k2 = generateDESkey();

byte[] edeKeyBytes = new byte[24];
System.arraycopy(k1.getEncoded(), 0, edeKeyBytes, 0, 8);
System.arraycopy(k2.getEncoded(), 0, edeKeyBytes, 8, 8);
System.arraycopy(k1.getEncoded(), 0, edeKeyBytes, 16, 8);

edeKey = new SecretKeySpec(edeKeyBytes, "DESede");

Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, edeKey);

System.out.println(Base64.encode(cipher.doFinal("plaintext".getBytes("UTF-8"))));

DESede使用三个键,我们称之为k1、k2和k3。它们都被连接成一个单字节数组。在您的情况下,k1被第二次用来代替k3。

那么当前代码有什么问题?有没有像BadPaddingException这样的异常?@ArtjomB。我将其更改为DESede,但如何从DESede的字符串生成密钥?另外,我正在寻找如何使用两个密钥的组合进行解密?而且,看起来您正在进行三重DES。这是需要的吗?请您编辑标题来描述您的问题,而不是您的目标。@Duncan说实话,我对密码学的实现不太了解,我想用它从纯字符串生成两个密钥,并用它们进行加密/解密。谢谢您的回答,这很有帮助。如何从纯字符串生成密钥,我在代码中没有看到。我没有。如果字符串不是密钥材料,而是某种密码,那么您可以使用类似PBKDF2的东西从字符串派生密钥。我会检查它,但如果您有一些如何从字符串派生密钥的示例,请告诉我。@ArtjomB。感谢您提到这个问题,它是有效的,但是如果我想在PBEWithMD5AndDES实例中使用自定义用户密钥,您知道怎么做吗?@firasalmanna如果您将字节[]转换为字符串,那么您需要无损地执行此操作。例如,使用Base64对其进行编码。简单地使用新的Stringbyte[]构造函数将导致字节丢失,因为密文可能有任何字节值,但字符串编码只支持某些字节值作为可打印字符。
SecretKey k1 = generateDESkey();
SecretKey k2 = generateDESkey();

byte[] edeKeyBytes = new byte[24];
System.arraycopy(k1.getEncoded(), 0, edeKeyBytes, 0, 8);
System.arraycopy(k2.getEncoded(), 0, edeKeyBytes, 8, 8);
System.arraycopy(k1.getEncoded(), 0, edeKeyBytes, 16, 8);

edeKey = new SecretKeySpec(edeKeyBytes, "DESede");

Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, edeKey);

System.out.println(Base64.encode(cipher.doFinal("plaintext".getBytes("UTF-8"))));