加密解密我自己生成的密钥而非Java生成的密钥

3

我对密码学很陌生,所以我有一个问题:

如何创建自己的密钥(比如像一个字符串“1234”)。因为我需要用密钥(由我定义)来加密一个字符串,将加密后的字符串保存在数据库中,当我想使用它时,从数据库中取出并用我知道的密钥解密它。

我有这段代码:

   import java.security.InvalidKeyException;
   import java.security.*;
   import javax.crypto.BadPaddingException;
   import javax.crypto.Cipher;
   import javax.crypto.IllegalBlockSizeException;
   import javax.crypto.SecretKey;
   import javax.crypto.SecretKeyFactory;
   import javax.crypto.spec.DESedeKeySpec;

      public class LocalEncrypter {

    private static String algorithm = "PBEWithMD5AndDES";
   //private static Key key = null;
    private static Cipher cipher = null;
    private static SecretKey key;

    private static void setUp() throws Exception {
        ///key = KeyGenerator.getInstance(algorithm).generateKey();
        SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
        String pass1 = "thisIsTheSecretKeyProvidedByMe";
        byte[] pass = pass1.getBytes(); 
        SecretKey key = factory.generateSecret(new DESedeKeySpec(pass));
        cipher = Cipher.getInstance(algorithm);
    }

    public static void main(String[] args) 
       throws Exception {
        setUp();

        byte[] encryptionBytes = null;
        String input = "1234";
        System.out.println("Entered: " + input);
        encryptionBytes = encrypt(input);
        System.out.println(
          "Recovered: " + decrypt(encryptionBytes));
    }

    private static byte[] encrypt(String input)
        throws InvalidKeyException, 
               BadPaddingException,
               IllegalBlockSizeException {
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] inputBytes = input.getBytes();
        return cipher.doFinal(inputBytes);
    }

    private static String decrypt(byte[] encryptionBytes)
        throws InvalidKeyException, 
               BadPaddingException,
               IllegalBlockSizeException {
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] recoveredBytes = 
          cipher.doFinal(encryptionBytes);
        String recovered = 
          new String(recoveredBytes);
        return recovered;
      }

}

   Exception in thread "main" java.security.spec.InvalidKeySpecException: Invalid key spec
at com.sun.crypto.provider.PBEKeyFactory.engineGenerateSecret(PBEKeyFactory.java:114)
at javax.crypto.SecretKeyFactory.generateSecret(SecretKeyFactory.java:335)
at LocalEncrypter.setUp(LocalEncrypter.java:22)
at LocalEncrypter.main(LocalEncrypter.java:28)
2个回答

5

KeyGenerator 生成随机密钥。由于您知道秘密密钥,所需的是 SecretKeyFactory。获取算法(DESede)的实例,然后使用 DESedeKeySpec 的实例作为参数调用其 generateSecret 方法:

SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey key = factory.generateSecret(new DESedeKeySpec(someByteArrayContainingAtLeast24Bytes));

这是一个完整可行的示例。正如我所说,DESedeKeySpec必须与DESede算法一起使用。使用DESede密钥与PBEWithMD5AndDES没有任何意义。

public class EncryptionTest {
    public static void main(String[] args) throws Exception {
        byte[] keyBytes = "1234567890azertyuiopqsdf".getBytes("ASCII");
        DESedeKeySpec keySpec = new DESedeKeySpec(keyBytes);
        SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
        SecretKey key = factory.generateSecret(keySpec);
        byte[] text = "Hello world".getBytes("ASCII");

        Cipher cipher = Cipher.getInstance("DESede");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encrypted = cipher.doFinal(text);

        cipher = Cipher.getInstance("DESede");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decrypted = cipher.doFinal(encrypted);
        System.out.println(new String(decrypted, "ASCII"));
    }
}

我不知道如何使用它,我尝试了SecretKeyFactory和许多变体,但都没有成功。 - user1069937
看看我的编辑。你应该在问题中展示你尝试过什么,并告诉我们哪些方法不起作用。 - JB Nizet
我将一个字符串转换成了byte[],使用了SecretKeyFactory,但现在它给我返回了错误:没有安装的提供程序支持此密钥:(null)。 SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede"); String pass1 = "123456789132456789123456789"; byte[] pass = pass1.getBytes(); SecretKey key = factory.generateSecret(new DESedeKeySpec(pass)); - user1069937
DESede在JRE中得到本地支持:请参见http://docs.oracle.com/javase/6/docs/technotes/guides/security/StandardNames.html#SecretKeyFactory。请编辑您的问题,包括代码、异常堆栈跟踪和可能安装的提供程序。 - JB Nizet
请在您的问题中编辑代码、异常堆栈跟踪和可能安装的提供程序。 - JB Nizet
显示剩余7条评论

0

好的,我在这里和那里结合起来找到了解决方案。加密结果将被格式化为Base64字符串,以便安全保存为xml文件。

package cmdCrypto;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.xml.bind.DatatypeConverter;

public class CmdCrypto {

    public static void main(String[] args) {
        try{
            final String strPassPhrase = "123456789012345678901234"; //min 24 chars

            String param = "No body can see me";
        System.out.println("Text : " + param);

            SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
            SecretKey key = factory.generateSecret(new DESedeKeySpec(strPassPhrase.getBytes()));
            Cipher cipher = Cipher.getInstance("DESede");

            cipher.init(Cipher.ENCRYPT_MODE, key);
            String str = DatatypeConverter.printBase64Binary(cipher.doFinal(param.getBytes()));
        System.out.println("Text Encryted : " + str);

            cipher.init(Cipher.DECRYPT_MODE, key);
        String str2 = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(str)));
        System.out.println("Text Decryted : " + str2);

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接