Java 如何从加密密码中解密密码

Java 如何从加密密码中解密密码,java,encryption,cryptography,secret-key,Java,Encryption,Cryptography,Secret Key,目前,我们正在对用户从登录页面输入的密码进行加密,并将其存储在数据库中。这里我开发了一个新的登录页面,用于内部目的,并重复使用相同的用户名和加密密码。如果用户获得授权,则将允许他访问报告。这里我的问题是,我如何获得他们用来加密的密钥。我想使用相同的密钥解密密码,我可以继续我的逻辑 这是我们用来加密密码的方法的代码 user = userRemote.loginUser(userName, new String(EncryptDecrypt.storePassword(password),"Cp1

目前,我们正在对用户从登录页面输入的密码进行加密,并将其存储在数据库中。这里我开发了一个新的登录页面,用于内部目的,并重复使用相同的用户名和加密密码。如果用户获得授权,则将允许他访问报告。这里我的问题是,我如何获得他们用来加密的密钥。我想使用相同的密钥解密密码,我可以继续我的逻辑

这是我们用来加密密码的方法的代码

user = userRemote.loginUser(userName, new String(EncryptDecrypt.storePassword(password),"Cp1252"));

Here password is Password entered in the login page.
final static byte[] salt = {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
    };
final static int count = 1;

public static byte[] storePassword(char[] password) throws InternalException {
      PBEKeySpec pbeKeySpec;
      PBEParameterSpec pbeParamSpec;
      SecretKeyFactory keyFac;
      byte[] ciphertext = null;
      try {
        // Install SunJCE provider
        Provider sunJce = new com.sun.crypto.provider.SunJCE();
        Security.addProvider(sunJce);

        // Create PBE parameter set
        pbeParamSpec = new PBEParameterSpec(salt, count);

        pbeKeySpec = new PBEKeySpec(password);
        keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
        // Create PBE Cipher
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

        // Initialize PBE Cipher with key and parameters
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

        // Our cleartext
        byte[] cleartext = (new String(password)).getBytes("Cp1252");

        // Encrypt the cleartext
        ciphertext = pbeCipher.doFinal(cleartext);
      } catch (BadPaddingException ex) {
        log.error("EncryptDecrypt: " + ex.getMessage());
        throw new InternalException(ex.getMessage());
      } catch (Exception ex) {
        log.error("EncryptDecrypt: " + ex.getMessage());
        throw new InternalException(ex.getMessage());
      }
     return ciphertext;
  }
这是加密密码的方法

user = userRemote.loginUser(userName, new String(EncryptDecrypt.storePassword(password),"Cp1252"));

Here password is Password entered in the login page.
final static byte[] salt = {
        (byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
        (byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
    };
final static int count = 1;

public static byte[] storePassword(char[] password) throws InternalException {
      PBEKeySpec pbeKeySpec;
      PBEParameterSpec pbeParamSpec;
      SecretKeyFactory keyFac;
      byte[] ciphertext = null;
      try {
        // Install SunJCE provider
        Provider sunJce = new com.sun.crypto.provider.SunJCE();
        Security.addProvider(sunJce);

        // Create PBE parameter set
        pbeParamSpec = new PBEParameterSpec(salt, count);

        pbeKeySpec = new PBEKeySpec(password);
        keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
        // Create PBE Cipher
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

        // Initialize PBE Cipher with key and parameters
        pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);

        // Our cleartext
        byte[] cleartext = (new String(password)).getBytes("Cp1252");

        // Encrypt the cleartext
        ciphertext = pbeCipher.doFinal(cleartext);
      } catch (BadPaddingException ex) {
        log.error("EncryptDecrypt: " + ex.getMessage());
        throw new InternalException(ex.getMessage());
      } catch (Exception ex) {
        log.error("EncryptDecrypt: " + ex.getMessage());
        throw new InternalException(ex.getMessage());
      }
     return ciphertext;
  }
这是我用来解密密码的类。这里我只有加密密码作为解密密码的输入。例如•Ä0 BÒO,所以我使用它来生成密钥并解密它。但是,下面是一个例外。 java.security.spec.InvalidKeySpecException:密码不是ASCII

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;

public class DecryptPassword {

    public static void main(String[] args) {
        String decryptedStr = checkPassword("•Ä0BÒ¦O");
        System.out.println("decryptedStr : "+decryptedStr);
    }

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

    final static int count = 1;

    static String decryptedPassword = "";

     public static String checkPassword(String encryptedPassword) {
          PBEKeySpec pbeKeySpec;
          PBEParameterSpec pbeParamSpec;
          SecretKeyFactory keyFac;
          try {
            // Install SunJCE provider
            Provider sunJce = new com.sun.crypto.provider.SunJCE();
            Security.addProvider(sunJce);
            // Create PBE parameter set
            pbeParamSpec = new PBEParameterSpec(salt, count);
            pbeKeySpec = new PBEKeySpec(encryptedPassword.toCharArray());
            keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
            SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
            // Create PBE Cipher
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
            // Initialize PBE Cipher with key and parameters
            pbeCipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec);
            byte[] decrypted = pbeCipher.doFinal(encryptedPassword.getBytes());
            decryptedPassword = decrypted.toString();
        } catch (BadPaddingException ex) {
          System.out.println("EncryptDecrypt: " + ex.getMessage());
        } catch (Exception ex) {
          System.out.println("EncryptDecrypt: " + ex.getMessage());
        }
        return decryptedPassword;
      }

}

在这里,我应该能够成功解密密码,但不是。谁能帮我这里缺少什么?提前感谢。

这不是加密,这是散列(篮筐投篮)

storePassword
例程有效地使用密码对自身进行加密;更确切地说,
PBEwithMD5andDES
使用原始PKCS5v1派生函数从密码派生的密钥,为了清晰起见,现在改名为PBKDF1,通过MD5、fixed salt和1(!)迭代实例化,用原始DES CBC加密密码。这是以前流行的创建加密哈希方法的变体

在20世纪60年代、70年代和80年代,在密码学家将注意力转向设计特定的加密散列函数(因此密码是唯一的加密原语)之前,将密码(密钥置换)转换为加密散列(未知函数)的常用方法是将数据用作密钥来加密常量;这方面的一个微小变化是作为一个库函数实现的,该函数的名称不准确,被用作ca 1970,并且仍然被记住(有时甚至被使用),但现在经常被重新命名为
DES crypt
descrypt
,以区别于此后开发的替代品和替换品

与设计用于解密的密码不同,这是一个哈希,设计用于不反转。我不知道有什么方法比暴力更容易扭转这种方法(即分析性的“断裂”),但最初的DES,现在通常称为单DES(或1DE),以区别于其直接后继的三DES(或3DES或正式的TDEA),已经足够弱了,如果你真的想的话,现在可以暴力强制。例如,对于单盐Decrypt,大约10-30米试验/秒,对于简单DES,大约相当于0.5克/秒,因此使用一台计算机尝试所有DES密钥需要几年时间,使用1000台计算机需要几天时间,使用一百万台计算机需要几分钟。关于hashcat的数据很难找到,但似乎大致相当。如果您知道密码是如何选择的,那么只尝试可能的密码而不是所有可能的密钥可能会更快


但是不要。验证密码散列的正确方法是用户提供所声明的密码,使用相同的参数重复散列过程(这里很容易,因为它没有使用应该使用的变量salt),然后查看新的哈希结果是否与存储的结果匹配。

我认为您根本不应该存储加密的密码。而不是这样做,存储更好。你到底为什么要解密密码?这是你最不想做的事。将密码散列并存储散列。当用户提供密码时,该密码将被散列并与存储的散列进行比较,以确保相等。只有用户才应该知道他或她的密码可能是什么。@DevilsHnd这里我的用例是有一个URL,可以在整个公司访问。我想把它限制在那些用户名和密码已经存在于数据库中的人身上。目前该密码已加密。除了解密密码并允许用户访问URL之外,还有什么更好的方法来授权用户吗?@Dannguyen密码已经加密(这是一个遗留应用程序),我只是尝试重新使用它们。底线是,如果你能解密密码,其他人也能解密密码。如果你给我一个加密密码,我最终可以解密它。另一方面,散列基本上是一种方式,而反转散列的可能性实际上是不可能的。散列不是加密,它是散列,因此无法解密。散列的唯一可能威胁是所谓的冲突,其中一个散列会以某种方式与另一个散列相同,例如使用相同的密码。即使这样也可以避免。您可能应该重新考虑您的密码安全模型。