Java 将字符串转换为AES的128位密钥

Java 将字符串转换为AES的128位密钥,java,encryption,Java,Encryption,我想输入自己的字符串变量,然后将其转换为AES算法加密/解密的密钥。我尝试过很多已知的方法,比如UTF-8、base64、一些转换字节字符串的方法,反之亦然,还有一些其他的方法。虽然它们确实都能工作,即使其中一些不能准确工作,但它们都以字节为单位转换字符串,但我想要的是输入类似“helloWorld”的内容,并为AES返回128位密钥。我使用的任何东西都是“无效密钥长度”,因为字节不准确。 我需要做什么才能获得正确的字节?我还想澄清我想要的是字符串,而不是字符数组,因为我想在以后的程序中将其作为

我想输入自己的字符串变量,然后将其转换为AES算法加密/解密的密钥。我尝试过很多已知的方法,比如UTF-8、base64、一些转换字节字符串的方法,反之亦然,还有一些其他的方法。虽然它们确实都能工作,即使其中一些不能准确工作,但它们都以字节为单位转换字符串,但我想要的是输入类似“helloWorld”的内容,并为AES返回128位密钥。我使用的任何东西都是“无效密钥长度”,因为字节不准确。 我需要做什么才能获得正确的字节?我还想澄清我想要的是字符串,而不是字符数组,因为我想在以后的程序中将其作为一个函数,以便用户可以在密钥受损时随意更改密钥

更新:我编辑了这个示例,但到目前为止,这个示例仍然抛出关于参数和键长度的异常

    public class SHAHashingExample
{
    private static byte[] keyValue;

    public static void main(String[] args)throws Exception
    {
        String password = "123456";

        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.update(password.getBytes());

        byte byteData[] = md.digest();
        keyValue = md.digest();

        //convert the byte to hex format method 1
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < byteData.length/2; i++) {
         sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }

        System.out.println("Hex format : " + sb.toString());

        //convert the byte to hex format method 2
        StringBuffer hexString = new StringBuffer();
        for (int i=0;i<byteData.length/2;i++) {
            String hex=Integer.toHexString(0xff & byteData[i]);
            if(hex.length()==1) hexString.append('0');
            hexString.append(hex);
        }
        System.out.println("Hex format : " + hexString.toString());

        String k = "hello world";
        String f = encrypt(k);
        System.out.println(f);
        String j = decrypt(f);
        System.out.println(j);
    }

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        String encryptedValue = new BASE64Encoder().encode(encVal);
        return encryptedValue;
    }

    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance("AES");
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception {
        Key key = new SecretKeySpec(keyValue, "AES");
        return key;
    }
}
公共类Shahashinge示例
{
私有静态字节[]键值;
公共静态void main(字符串[]args)引发异常
{
字符串密码=“123456”;
MessageDigest md=MessageDigest.getInstance(“SHA-256”);
md.update(password.getBytes());
byte byteData[]=md.digest();
keyValue=md.digest();
//将字节转换为十六进制格式方法1
StringBuffer sb=新的StringBuffer();
for(int i=0;i对于(int i=0;i来说,您正在寻找的被称为a。您将能够输入任意长度的输入,并且哈希函数将始终输出一个固定位大小的值——在您的情况下为128位

散列函数有很多方法。最简单的方法是在输入数字(例如字符串的整数表示)和可以用n位表示的最大数字(在您的例子中为128位)之间进行比较;输出结果将是一个n位数字,您可以将其转换为任何形式(可能是十六进制)并将其用作AES密钥

这并不一定是有效的(也就是说,输出128位密钥可能在0和2^128-1之间分布不均匀),但是——更重要的是,它会非常慢,没有什么好的理由。一些有效的128位哈希函数是CityHash和MurruHash——您可以查看更多信息(以及一些Java实现)在谷歌上。

更新2: 事实证明,您对Java密码功能的许多组件的使用并不恰当

更新1: 要使用下面的示例将256位值降至128位,请尝试以下操作:

// After you already have generated the digest
byte[] mdbytes = md.digest();
byte[] key = new byte[mdbytes.length / 2];

for(int I = 0; I < key.length; I++){
    // Choice 1 for using only 128 bits of the 256 generated
    key[I] = mdbytes[I];

    // Choice 2 for using ALL of the 256 bits generated
    key[I] = mdbytes[I] ^ mdbytes[I + key.length];
}

// Now use key as the input key for AES
//在您已经生成摘要之后
byte[]mdbytes=md.digest();
字节[]键=新字节[mdbytes.length/2];
for(int I=0;I
原件: 下面是一个使用内置JavaAPI对某些数据字节执行SHA哈希的好例子

Java具有执行多种不同哈希类型的内置功能,您确实应该尝试利用其中的一种,而不是自己编写。可能最广泛使用的哈希函数是SHA版本。有些版本可以输出128、256和512位的哈希输出


您所要求的是,在所有技术上,使用您的密码登录系统通常是如何工作的。系统从不真正存储您的实际文本密码,而是对其进行哈希。当您(用户)输入密码时,系统会对您输入的内容执行实时哈希,并将实时生成的哈希与e存储的散列。这并不是说使用散列作为对称加密的实际密钥组件的附加步骤。一般来说,一个好的散列确实可以生成用于实际对称加密/解密的像样的密钥材料。

这并不能告诉我太多,当然我没有找到,我很感谢你的帮助但是我发现基于派生的示例太复杂,或者出于任何原因使用了一些来散列密码。我想要的是类似这样的简单实现:AESKey ak=hash(“mypassword”);像这样简单的事情。当然,如果有一个现成的方法,那么请告诉我它是哪一个,如果不是,我希望有一个非常简单的例子。因此,首先从您的代码来看,您在使用
generateKey
例程时正在动态生成密钥。这样,您就不会实际使用转换为使用散列作为实际密钥的密钥。您可能也希望在此处查看。这实际上不是问题,因为generateKey方法使用我自己的字段,该字段在main中初始化。我还更改了参数,在初始化后将密钥作为参数提供,其工作原理完全相同。要澄清,您的问题可能在于转换如果您在使用十六进制值的特定接口上使用键,则将数字转换为十六进制形式。这意味着转换721(十进制)或1010001(二进制)之类的值Java的Integer类有一个内置的方法来实现这一点。实际上,他并不想转换为十六进制字符串,除非他想显示散列的输出,也不想在实际执行散列之前转换字符串。你可能是对的。这取决于他以后想如何使用它们的键。如果他是encr在他的内心隐藏着某种东西