Java 从字符串生成密钥?

Java 从字符串生成密钥?,java,cryptography,key,Java,Cryptography,Key,我需要从一个字符串生成一个键,这样我就可以始终从同一个字符串创建同一个键。(特别是一个密钥对象,这样我就可以用它来创建一个密码,然后再创建一个SealedObject) 这在Java中可能吗?我应该考虑什么类/方法组合才能做到这一点?对于AES加密: SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(password, salt,

我需要从一个字符串生成一个键,这样我就可以始终从同一个字符串创建同一个键。(特别是一个密钥对象,这样我就可以用它来创建一个密码,然后再创建一个SealedObject)

这在Java中可能吗?我应该考虑什么类/方法组合才能做到这一点?

对于AES加密:

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);

byte[] iv = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
byte[] ciphertext = cipher.doFinal("Hello, World!".getBytes("UTF-8"));

// reinit cypher using param spec
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(iv));
类似地,对于不推荐使用的PBKDF1和不安全的DES,用于与遗留系统通信学习目的

byte[] salt = {
    (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
    (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};

int count = 20;

PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, count);
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES");
cipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

SealedObject sealed = new SealedObject(object, cipher);
...

请注意,在上一个示例中,迭代计数也太低。

您可以通过对Java进行加密来实现这一点

首先,您需要两个罐子:

  • 下面是如何在Java中使用的完整示例:

    用法:

    KeyGen keyGen = KeyGen.getInstance();
    String string = "JOYMAA";
    String enc = keyGen.encrypt(string);
    System.out.println(enc);
    String dec = keyGen.decrypt(enc);
    System.out.println(dec);
    
    希望这将对您有所帮助。

    您希望为此使用或。根据我的经验,前者的应用更为广泛。基于此,java似乎确实支持这一点

    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
    SecretKey tmp = factory.generateSecret(spec);
    SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES");
    

    这些都过时了。唯一修改过的算法是Argon2id。它位于更新版本的Bouncycastle中:

    如果内存不足,请在执行参数中使用“-Xmx8G”

    private SecretKey genKey(char[] passwordChars, byte[] saltBytes) {
    SecretKey aesKey;
        int aesKeyLen = 16; //key len in bytes
        int version = Argon2Parameters.ARGON2_VERSION_13;
        int iterations = 1;
        int memory = 22; // 20 = 1 GB -> 22=4GB
        int parallelism = 16; //double CPU core
        Argon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)
                .withVersion(version).withIterations(iterations).withMemoryPowOfTwo(memory) // use 2^(memory) KB
                .withParallelism(parallelism).withSalt(saltBytes);
        Argon2BytesGenerator gen = new Argon2BytesGenerator();
        gen.init(builder.build());
        byte[] result = new byte[aesKeyLen];
        gen.generateBytes(passwordChars, result, 0, result.length);
        aesKey = new SecretKeySpec(result, "AES");
    //clear to free RAM
        builder = null;
        gen = null;
        System.gc();
    return aesKey;
    }
    

    hashCode()
    能帮你吗?如果没有-为什么?据我所知没有,因为我试图创建一个SealedObject来封装一个对象以进行传输:我没有试图将明文字符串混淆成散列,我正在尝试创建一个键(对象)。需要明确的是,如果我使用相同的密码在服务器端执行相同的操作,它将生成一个密码,可以用来解密SealeObject?这是正确的。只要您使用相同的参数和密钥规格,您将拥有相同的密钥。如果删除前半部分,这将是一个更好的答案。DES在今天已经完全被破坏了,即使作为一个例子使用它也是危险的(人们可能会在不知道它不安全的情况下复制它)。DES甚至对于这些类型的东西都非常过时。它是易碎的,如果你使用它做任何有安全要求的事情,直接des的出现可能会给你带来麻烦。谢谢你提供了额外的细节,伙计们。我一定会使用AES版本。ECB模式加密也不会。让一个名为
    KeyGen
    的类执行加密/解密也不会给你带来太多希望。我的意思是,这是一个9年前的问题。。。。答案现在已经过时,这并不完全令人惊讶
    private SecretKey genKey(char[] passwordChars, byte[] saltBytes) {
    SecretKey aesKey;
        int aesKeyLen = 16; //key len in bytes
        int version = Argon2Parameters.ARGON2_VERSION_13;
        int iterations = 1;
        int memory = 22; // 20 = 1 GB -> 22=4GB
        int parallelism = 16; //double CPU core
        Argon2Parameters.Builder builder = new Argon2Parameters.Builder(Argon2Parameters.ARGON2_id)
                .withVersion(version).withIterations(iterations).withMemoryPowOfTwo(memory) // use 2^(memory) KB
                .withParallelism(parallelism).withSalt(saltBytes);
        Argon2BytesGenerator gen = new Argon2BytesGenerator();
        gen.init(builder.build());
        byte[] result = new byte[aesKeyLen];
        gen.generateBytes(passwordChars, result, 0, result.length);
        aesKey = new SecretKeySpec(result, "AES");
    //clear to free RAM
        builder = null;
        gen = null;
        System.gc();
    return aesKey;
    }