java - 在Java中生成并使用两个 key 进行加密和解密

标签 java encryption cryptography des

我正在开发一个 Java 应用程序,需要使用两个 key 从不同的字符串生成用于加密和解密。一 字符串来自用户,其他是主 key 。我在网上看的 并找到了一些有关它的引用资料。我真的很想要一些 帮助了解如何实现这一点。我会展示我现在拥有的。

正如你从代码中看到的,我使用了其他 stackoverflow 帖子中的一些代码并对其进行了一些修改。我只是不知道如何从 2 个字符串生成 2 个 key ,以及如何从哪里获取用于解密的 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;
}

}

如果有任何困惑或疑问。请告诉我。

最佳答案

回答更改之前的代码。

您尝试仅使用两个 key 而不是三个 key 来执行 DESede。

这通常可能有效,但并不像您所写的那样。问题在于填充。在第二步中,您尝试使用其他 key 而不是加密 key 来解密密文,因此解密将在 256 次中失败超过 255 次,因为填充将是错误的(也因为您使用 Base64 编码没有必要)。

如果你真的想这样做,你将不得不在没有填充和没有 Base64 编码的情况下解密。好处是未编码的密文已经是 block 大小的倍数,因此不会阻止您使用“DES/ECB/NoPadding”

public static void main(String[] args) {
    // First I would like to create keys by giving Strings
    SecretKey k1 = generateDESkey();
    SecretKey k2 = generateDESkey();

    // encryption
    byte[] firstEncryption = desEncryption("plaintext".getBytes("UTF-8"), k1, false);
    byte[] decryption = desDecryption(firstEncryption, k2, true);
    byte[] secondEncryption = desEncryption(decryption, k1, true);

    // decryption
    byte[] firstDecryption = desDecryption(secondEncryption, k1, true);
    byte[] encryption = desEncryption(firstDecryption, k2, true);
    byte[] secondDecryption = desDecryption(encryption, k1, false);

    System.out.println(new String(secondDecryption)); // plaintext
}

public static byte[] desEncryption(byte[] strToEncrypt, SecretKey desKey, boolean noPadding) {
    try {
        Cipher cipher = Cipher.getInstance(noPadding ? "DES/ECB/NoPadding" : "DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, desKey);
        return cipher.doFinal(strToEncrypt);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

public static byte[] desDecryption(byte[] strToDecrypt, SecretKey desKey, boolean noPadding) {
    try {
        Cipher cipher = Cipher.getInstance(noPadding ? "DES/ECB/NoPadding" : "DES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, desKey);
        return cipher.doFinal(strToDecrypt);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

当通用 key 以这种方式构造时,这实际上是具有两个 key 的 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 使用三个 key ,我们将其称为 k1、k2 和 k3。它们全部连接成一个字节数组。在您的情况下,k1 被第二次用来代替 k3。

关于java - 在Java中生成并使用两个 key 进行加密和解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28875731/

相关文章:

java - 模拟的模拟 Actor

java - 关于并行运行线程并在之后返回

security - Base 64 编码的目的是什么?为什么在 HTTP 基本身份验证中使用它?

encryption - 加密连接字符串 IIS 7

javascript - 在线游戏 : A fast not-so-secure cryptographic hashing/a checksum function in JavaScript?

java - 消除未经检查的警告: cast String to T

java - 添加异步任务功能?

web-services - 为什么要使用 x.509 证书来加密 xml?为什么不直接通过 https 传输?

authentication - Java - PBKDF2 以 HMACSHA256 作为 PRF

delphi - 如何获取加密数据的大小?