Java 如何使用 MessageDigest 和 Base64 进行解码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3479067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to decode with MessageDigest , Base64
提问by Perry
I am currently encoding a password. I have to decode the password. Here is the code to encode. I am trying to get the original password compare it. I have researched about MessageDigest that says it is a one-way method. Not sure how to get the original message. We have a decode method but it isn't giving me the original password - Base64.decode.
我目前正在对密码进行编码。我必须解码密码。这是要编码的代码。我正在尝试获取原始密码进行比较。我研究过 MessageDigest 说它是一种单向方法。不知道如何获取原始消息。我们有一个解码方法,但它没有给我原始密码 - Base64.decode。
public static synchronized String getMD5_Base64(String input) {
if (!isInited) {
isInited = true;
try {
digest = MessageDigest.getInstance("MD5");
} catch (Exception ex) {
}
}
if (digest == null)
return input;
// now everything is ok, go ahead
try {
digest.update(input.getBytes("UTF-8"));
} catch (java.io.UnsupportedEncodingException ex) {
}
byte[] rawData = digest.digest();
byte[] encoded = Base64.encode(rawData);
String retValue = new String(encoded);
return retValue;
}
}
回答by Jherico
You cannot get the original password. Keep in mind that the digest and Base64 encoding do two completely different things. The MD5 digest creates a cryptographic hash of the data supplied to it. This is irreversible. Base64 is an encoding mechanism to convert data (which might contain unprintable binary data) into a string that is guaranteed to contain only printable characters. This step is reversible.
您无法获得原始密码。请记住,摘要和 Base64 编码做两件完全不同的事情。MD5 摘要创建提供给它的数据的加密散列。这是不可逆的。Base64 是一种编码机制,可将数据(可能包含不可打印的二进制数据)转换为保证仅包含可打印字符的字符串。这一步是可逆的。
The standard way of checking a password is not to decode the original password and compare the plain text. What you need to do is take the encoding (MD5 hash then Base64 encode) you did on the original password and apply it to the newly supplied password. Then compare the stored encoded version with the newly encoded version. If they're the same then the passwords matched.
检查密码的标准方法不是解码原始密码并比较纯文本。您需要做的是采用您对原始密码所做的编码(MD5 哈希然后 Base64 编码)并将其应用于新提供的密码。然后将存储的编码版本与新编码的版本进行比较。如果它们相同,则密码匹配。
This design is a more secure mechanism than storing passwords that could be decoded. This way, if someone steals your password database they don't automatically have access to all the passwords of your users. In order to break into the system they'd still have to find a password that encoded to the same value. The point of cryptographic hashes like MD5 is to make that very difficult. On the other hand, MD5 is not considered a very secure hash anymore. You'd be better off using SHA1 or SHA256 (but remember, you can't change the existing stored passwords from their MD5 hash to another hash without the original password, which you don't have, i.e. you can't just convert your database of stored passwords).
这种设计是一种比存储可以解码的密码更安全的机制。这样,如果有人窃取了您的密码数据库,他们就不会自动访问您用户的所有密码。为了闯入系统,他们仍然必须找到编码为相同值的密码。像 MD5 这样的加密散列的重点是让这变得非常困难。另一方面,MD5 不再被认为是非常安全的哈希。您最好使用 SHA1 或 SHA256(但请记住,您不能将现有存储的密码从其 MD5 哈希更改为另一个没有原始密码的哈希,即您没有原始密码,即您不能只是转换您的存储密码的数据库)。
回答by Borealid
The MD5 hash algorithm is, like all hash algorithms, one-way. The only way to recover the original password is to try every possibility until you get the one whose MD5 hash matches what you received.
与所有哈希算法一样,MD5 哈希算法是单向的。恢复原始密码的唯一方法是尝试每一种可能性,直到获得 MD5 哈希与您收到的密码相匹配的密码。
回答by jmo
If you're trying to compare the contents of the new password with the older passwords you can't use an MD5 hash. As Jherico noted, MD5 (and all hashes) are one-way meaning that you can't get the original text.
如果您尝试将新密码的内容与旧密码的内容进行比较,则不能使用 MD5 哈希。正如 Jherico 所指出的,MD5(和所有散列)是单向的,这意味着您无法获得原始文本。
In order to do the compare you will have to keep the original value of the password around somewhere. The best way is probably to encrypt (and base64 the result) before storing it to the database. Then in order to do the compare, you decrypt each of the values and do the work that you want
为了进行比较,您必须将密码的原始值保留在某处。最好的方法可能是在将它存储到数据库之前加密(和 base64 结果)。然后为了进行比较,您解密每个值并执行您想要的工作
One important note is that storing the user's passwords in any form that can be reversed is can be dangerous if not done properly.
一个重要的注意事项是,以任何可以逆转的形式存储用户的密码,如果操作不当,可能会很危险。
回答by Narayan Subedi
MessageDigest with MD5 is one way hash. So, why don't you use javax.cryptowhich can encrypt and decrypt easily. Here is the example:
带有 MD5 的 MessageDigest 是一种方式哈希。那么,为什么不使用可以轻松加密和解密的javax.crypto。这是示例:
import java.security.spec.KeySpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Base64;
public class EncryptDecrypt {
private static final String UNICODE_FORMAT = "UTF8";
public static final String DESEDE_ENCRYPTION_SCHEME = "DESede";
private KeySpec ks;
private SecretKeyFactory skf;
private Cipher cipher;
byte[] arrayBytes;
private String myEncryptionKey;
private String myEncryptionScheme;
SecretKey key;
public EncryptDecrypt() throws Exception {
myEncryptionKey = "ThisIsSpartaThisIsSparta";
myEncryptionScheme = DESEDE_ENCRYPTION_SCHEME;
arrayBytes = myEncryptionKey.getBytes(UNICODE_FORMAT);
ks = new DESedeKeySpec(arrayBytes);
skf = SecretKeyFactory.getInstance(myEncryptionScheme);
cipher = Cipher.getInstance(myEncryptionScheme);
key = skf.generateSecret(ks);
}
public String encrypt(String unencryptedString) {
String encryptedString = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] plainText = unencryptedString.getBytes(UNICODE_FORMAT);
byte[] encryptedText = cipher.doFinal(plainText);
encryptedString = new String(Base64.encodeBase64(encryptedText));
} catch (Exception e) {
e.printStackTrace();
}
return encryptedString;
}
public String decrypt(String encryptedString) {
String decryptedText=null;
try {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] encryptedText = Base64.decodeBase64(encryptedString.getBytes());
byte[] plainText = cipher.doFinal(encryptedText);
decryptedText= new String(plainText);
} catch (Exception e) {
e.printStackTrace();
}
return decryptedText;
}
public static void main(String args []) throws Exception
{
EncryptDecrypt td= new EncryptDecrypt();
String target="password@123";
String encrypted=td.encrypt(target);
String decrypted=td.decrypt(encrypted);
System.out.println("String To Encrypt: "+ target);
System.out.println("Encrypted String: " + encrypted);
System.out.println("Decrypted String: " + decrypted);
}
}