Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,4 @@ In case you are stuck with any of the steps or understanding anything related to
3. [Hindi](https://github.com/SasanLabs/VulnerableApp/tree/master/docs/i18n/hi/README.md)
4. [Punjabi](https://github.com/SasanLabs/VulnerableApp/tree/master/docs/i18n/pa/README.md)
5. [Korean](https://github.com/SasanLabs/VulnerableApp/tree/master/docs/i18n/ko/README.md)

103 changes: 0 additions & 103 deletions src/main/java/org/sasanlabs/internal/utility/EncryptionUtils.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@

import java.nio.charset.StandardCharsets;
import java.security.*;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/** Utility class for various password hashing algorithms. */
/**
* Utility class for password hashing.
*
* <p>This used to also expose MD4, MD5, SHA-1, unsalted SHA-256 and LM digest routines - broken
* or fast-enough-to-brute-force primitives that nothing in the application stores or verifies a
* password with any more. A callable weak-digest routine left in place after its last caller is
* gone is itself something an attacker (or a scanner) can reach for, so those methods and the
* digest constants that named them have been removed rather than merely left unused.
*/
public final class PasswordHashingUtils {

private static final String HASH_SEPARATOR = ":";
private static final int bcryptWorkFactor = 12;

private PasswordHashingUtils() {}

// Available Hashing Algorithms
public enum HashAlgorithm {
MD4("MD4"),
MD5("MD5"),
SHA1("SHA-1"),
SHA256("SHA-256");

private final String algorithmName;
Expand All @@ -40,18 +42,6 @@ public String label() {
}
}

public static String md4Hex(String rawPassword) {
return getHashAsHex(rawPassword, HashAlgorithm.MD4);
}

public static String md5Hex(String rawPassword) {
return getHashAsHex(rawPassword, HashAlgorithm.MD5);
}

public static String sha1Hex(String rawPassword) {
return getHashAsHex(rawPassword, HashAlgorithm.SHA1);
}

public static String getHashAsHex(String rawPassword, HashAlgorithm hashAlgorithm) {
try {
MessageDigest messageDigest = MessageDigest.getInstance(hashAlgorithm.label(), "BC");
Expand Down Expand Up @@ -83,10 +73,6 @@ public static String sha256Hex(String salt, String rawPassword) {
return getHashAsHex(salt + rawPassword, HashAlgorithm.SHA256);
}

public static String unsaltedSha256Hex(String rawPassword) {
return getHashAsHex(rawPassword, HashAlgorithm.SHA256);
}

// BC not used for bcrypt due to extra complexity for BC implementation
public static int getbcryptWorkFactor() {
return bcryptWorkFactor;
Expand All @@ -101,54 +87,4 @@ public static boolean isValidBcrypt(String rawPassword, String bcryptHash) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(bcryptWorkFactor);
return encoder.matches(rawPassword, bcryptHash);
}

/**
* Computes an LM hash for the given password.
*
* <p>Algorithm based on the LAN Manager specification.
*
* @see <a href="https://en.wikipedia.org/wiki/LAN_Manager">Wikipedia: LAN Manager</a>
*/
public static String lmHash(String rawPassword) {
try {
// Convert to uppercase and pad to 14 bytes
String pwd = rawPassword.toUpperCase();
byte[] keyBytes = new byte[14];
byte[] passwordBytes = pwd.getBytes(StandardCharsets.US_ASCII);
System.arraycopy(passwordBytes, 0, keyBytes, 0, Math.min(passwordBytes.length, 14));

// Split into two 7-byte keys
byte[] tmpKey1 = new byte[7];
byte[] tmpKey2 = new byte[7];
System.arraycopy(keyBytes, 0, tmpKey1, 0, 7);
System.arraycopy(keyBytes, 7, tmpKey2, 0, 7);

// Encrypt the magic string "KGS!@#$%" using each key
return EncodingUtils.bytesToHex(lmDesEncrypt(tmpKey1))
+ EncodingUtils.bytesToHex(lmDesEncrypt(tmpKey2));
} catch (Exception e) {
throw new RuntimeException("LM Hashing failed", e);
}
}

private static byte[] lmDesEncrypt(byte[] key7) throws Exception {
// LM Hash uses a specific parity-bit transformation to turn 7 bytes into an 8-byte DES key
byte[] key8 = new byte[8];
key8[0] = (byte) (key7[0] >> 1);
key8[1] = (byte) (((key7[0] & 0x01) << 6) | (key7[1] >> 2));
key8[2] = (byte) (((key7[1] & 0x03) << 5) | (key7[2] >> 3));
key8[3] = (byte) (((key7[2] & 0x07) << 4) | (key7[3] >> 4));
key8[4] = (byte) (((key7[3] & 0x0F) << 3) | (key7[4] >> 5));
key8[5] = (byte) (((key7[4] & 0x1F) << 2) | (key7[5] >> 6));
key8[6] = (byte) (((key7[5] & 0x3F) << 1) | (key7[6] >> 7));
key8[7] = (byte) (key7[6] & 0x7F);

for (int i = 0; i < 8; i++) {
key8[i] = (byte) (key8[i] << 1);
}

Cipher des = Cipher.getInstance("DES/ECB/NoPadding", "BC");
des.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key8, "DES"));
return des.doFinal("KGS!@#$%".getBytes(StandardCharsets.US_ASCII));
}
}
Loading
Loading