加密哈希是一种哈希函数,它接受随机大小的输入并产生固定大小的输出。计算容易,但检索原始数据具有挑战性。使用唯一输入复制相同的哈希非常强大且困难,并且是一种单向函数,因此无法还原。散列也有不同的名称,如摘要、消息摘要、校验和等。
密码学散列函数
理想的加密散列函数具有以下主要属性:
- 确定性:这意味着相同的消息总是产生相同的哈希值。
- 快速:可以快速计算任何给定消息的哈希值。
- 雪崩效应:这意味着消息中的每一个微小变化都会导致散列值的重大变化。
- 单向函数:您无法反转加密哈希函数来获取数据。
- 抗冲突性:找到产生相同哈希值的两条不同消息是不可行的。
破解哈希
我们经常听到 Cracking a Hash 这个词,有几种方法可以做到:
- 找到一种算法来生成两个散列之间的冲突。算法越先进,破解哈希就越困难。
- 另一种方法是找到一种算法来识别将产生给定散列的唯一且不同的输入。它类似于碰撞,但不是碰撞,我们专注于使用算法找到输入。
- 我们今天仍在使用的一些从密码学角度被认为是“破解”的常见哈希是 MD5(消息摘要算法)和 SHA-1(安全哈希算法 1)。请记住,这些是技术上损坏的哈希,永远不会用于您的安全目的。
如何创建加密哈希
- 使用 SecureRandom 类创建随机盐值,SecureRandom 类生成强随机值。 engineNextBytes(byte[] bytes) 方法用于生成用户指定数量的随机字节。
- 使用 ByteArrayOutputStream 类将两组字节转换为一组并将其创建为 ByteArray。
- 创建一个通过 SHA2_ALGORITHM 的 messageDigest 实例,该实例返回给定输入值的哈希值。
- UUID 用于生成转换为字符串并作为输入传递的随机数。
- 可以使用 DatatypeConverter 将返回的对象转换为十六进制二进制格式。
Java
// Java program to demonstrate
// how to create a Hash
package java_cryptography;
import java.io.ByteArrayOutputStream;
import java.security.MessageDigest;
import java.util.UUID;
import javax.xml.bind.DatatypeConverter;
import sun.security.provider.SecureRandom;
public class Hashing {
// Initializing the final string variable
private static final String SHA2_ALGORITHM
= "SHA-256";
// Creating a random salt value to prevent
// attacks from the Rainbow table.
public static byte[] Creating_Random_Salt()
{
byte[] salt = new byte[16];
SecureRandom secure_random
= new SecureRandom();
secure_random.engineNextBytes(salt);
return salt;
}
// Creating hash value using input value
// and salt using the SHA2 Algorithm.
public static byte[] Creating_SHA2_Hash(
String input, byte[] salt) throws Exception
{
ByteArrayOutputStream byte_Stream
= new ByteArrayOutputStream();
byte_Stream.write(salt);
byte_Stream.write(input.getBytes());
byte[] valueToHash
= byte_Stream.toByteArray();
MessageDigest messageDigest
= MessageDigest
.getInstance(SHA2_ALGORITHM);
return messageDigest
.digest(valueToHash);
}
public static void main(String args[])
throws Exception
{
// Calling the function Creating_Random_Salt()
// to generate a random salt value
byte[] salt = Creating_Random_Salt();
System.out.println(
"SALT_VALUE: "
+ DatatypeConverter.printHexBinary(salt));
String valueToHash
= UUID.randomUUID().toString();
// Generating first hash with the salt
byte[] hash1
= Creating_SHA2_Hash(valueToHash, salt);
// Generating second hash with exact salt
// to check if we get the same hash.
byte[] hash2
= Creating_SHA2_Hash(valueToHash, salt);
// Print first and the second hash value
System.out.println(
"HASH1_VALUE: "
+ DatatypeConverter
.printHexBinary(hash1));
System.out.println(
"HASH2_VALUE: "
+ DatatypeConverter
.printHexBinary(hash2));
}
}
Java
// Java program to demonstrate
// how to hash a password
package java_cryptography;
import java.util.Scanner;
import org.springframework
.security
.crypto
.bcrypt
.BCrypt;
public class Hashing {
// Creating a private instance
// of Scanner class
private static Scanner sc;
// BCrypt is a password Hashing
// Function based on Blowfish
// Algorithm.
public static String Password_Hash(
String password)
{
return BCrypt.hashpw(
password, BCrypt.gensalt());
}
// Verifying password with the
// hashed password.
public static boolean Verify_Password(
String password,
String hashed_password)
{
return BCrypt.checkpw(
password, hashed_password);
}
public static void main(
String args[]) throws Exception
{
// Scanner class instance connected
// to the Input Stream(System.in)
sc = new Scanner(System.in);
System.out.println(
"Enter the password: ");
// Scanner class instance
// reading the user input
String p = sc.nextLine();
// Generate hashed password
String passwordHash
= Password_Hash(p);
// Print Hashed Password
System.out.println(
"Hashed-password: "
+ passwordHash);
// Printing the result of verification
// of hashed password
// with original password
System.out.println(
"Verification: "
+ Verify_Password(
p, passwordHash));
}
}
注意: Salt 是添加到输入数据(密码)中的随机值,用于防御预先计算的哈希攻击,例如 Rainbow 表。
输出:
SALT_VALUE: A96BB94B1FDACDD9B5FDDFFF2E173366
HASH1_VALUE: 53C77F310EEBCBDA585E9458BCA02715555624D9838190AC7DB5F7FA424C8429
HASH2_VALUE: 53C77F310EEBCBDA585E9458BCA02715555624D9838190AC7DB5F7FA424C8429
如何创建加密散列密码
正如我们现在已经看到如何生成哈希,让我们使用 Bcrypt 来哈希密码。不要对散列密码使用损坏的散列算法。 Bcrypt 是一个基于 Blowfish Cipher 的密码哈希函数。
方法:
- 将密码传递给 Bcrypt 类中的 hashpw函数,该函数也可以自行生成盐并返回一个字符串。
- 使用 checkpw()函数验证密码哈希和密码是否真的匹配。它返回一个布尔值。
代码:
Java
// Java program to demonstrate
// how to hash a password
package java_cryptography;
import java.util.Scanner;
import org.springframework
.security
.crypto
.bcrypt
.BCrypt;
public class Hashing {
// Creating a private instance
// of Scanner class
private static Scanner sc;
// BCrypt is a password Hashing
// Function based on Blowfish
// Algorithm.
public static String Password_Hash(
String password)
{
return BCrypt.hashpw(
password, BCrypt.gensalt());
}
// Verifying password with the
// hashed password.
public static boolean Verify_Password(
String password,
String hashed_password)
{
return BCrypt.checkpw(
password, hashed_password);
}
public static void main(
String args[]) throws Exception
{
// Scanner class instance connected
// to the Input Stream(System.in)
sc = new Scanner(System.in);
System.out.println(
"Enter the password: ");
// Scanner class instance
// reading the user input
String p = sc.nextLine();
// Generate hashed password
String passwordHash
= Password_Hash(p);
// Print Hashed Password
System.out.println(
"Hashed-password: "
+ passwordHash);
// Printing the result of verification
// of hashed password
// with original password
System.out.println(
"Verification: "
+ Verify_Password(
p, passwordHash));
}
}
输出:
Input: Enter the password: GEEKS FOR GEEKS
Output: Hashed-password: $2a$10$u6MFjykfR76nHGfhYYzjjOOe1I3EY.YxpQY4vKRHpKRCqz7w69RTa
Verification: true
哈希使用
- 数字签名。
- 数字指纹。
- 记录敏感数据。
- 保存密码。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。