Skip to content

Commit

Permalink
#99: argon2 conversion to operation on bytesù
Browse files Browse the repository at this point in the history
  • Loading branch information
firaja committed Feb 15, 2023
1 parent 26a94d0 commit c9bcc24
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 64 deletions.
137 changes: 78 additions & 59 deletions src/main/java/com/password4j/Argon2Function.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,84 @@ public static Argon2Function getInstanceFromHash(String hashed)
return getInstance(memory, iterations, parallelism, outputLength, type, version);
}

@Override
public Hash hash(CharSequence plainTextPassword)
{
byte[] salt = SaltGenerator.generate();
return internalHash(Utils.fromCharSequenceToBytes(plainTextPassword), salt, null);
}

@Override
public Hash hash(CharSequence plainTextPassword, String salt)
{
return hash(plainTextPassword, salt, null);
}

public Hash hash(byte[] plainTextPassword, byte[] salt)
{
return hash(plainTextPassword, salt, null);
}

@Override
public Hash hash(CharSequence plainTextPassword, String salt, CharSequence pepper)
{
return internalHash(Utils.fromCharSequenceToBytes(plainTextPassword), Utils.fromCharSequenceToBytes(salt), pepper);
}

public Hash hash(byte[] plainTextPassword, byte[] salt, CharSequence pepper)
{
return internalHash(plainTextPassword, salt, pepper);
}

private Hash internalHash(byte[] plainTextPassword, byte[] salt, CharSequence pepper)
{
long[][] blockMemory = copyOf(initialBlockMemory);

if (salt == null)
{
salt = SaltGenerator.generate();
}
initialize(plainTextPassword, salt, Utils.fromCharSequenceToBytes(pepper), null, blockMemory);
fillMemoryBlocks(blockMemory);
byte[] hash = ending(blockMemory);
Hash result = new Hash(this, encodeHash(hash, salt), hash, Utils.fromBytesToString(salt));
result.setPepper(pepper);
return result;
}

@Override
public boolean check(CharSequence plainTextPassword, String hashed)
{
Object[] params = decodeHash(hashed);
return check(plainTextPassword, hashed, Utils.fromBytesToString((byte[]) params[5]), null);
}

@Override
public boolean check(CharSequence plainTextPassword, String hashed, String salt, CharSequence pepper)
{
byte[] plainTextPasswordAsBytes = Utils.fromCharSequenceToBytes(plainTextPassword);
byte[] saltAsBytes = Utils.fromCharSequenceToBytes(salt);
byte[] hashedAsBytes = Utils.fromCharSequenceToBytes(hashed);
return check(plainTextPasswordAsBytes, hashedAsBytes, saltAsBytes, pepper);
}

public boolean check(byte[] plainTextPassword, byte[] hashed, byte[] salt, CharSequence pepper)
{
byte[] theSalt;
if (salt == null || salt.length == 0)
{
Object[] params = decodeHash(Utils.fromBytesToString(hashed));
theSalt = (byte[]) params[5];
}
else
{
theSalt = salt;
}

Hash internalHash = internalHash(plainTextPassword, theSalt, pepper);
return slowEquals(internalHash.getResultAsBytes(), hashed);
}

protected static String getUID(int memory, int iterations, int parallelism, int outputLength, Argon2 type, int version)
{
return memory + "|" + iterations + "|" + parallelism + "|" + outputLength + "|" + type.ordinal() + "|" + version;
Expand Down Expand Up @@ -319,66 +397,7 @@ protected static String toString(int memory, int iterations, int parallelism, in
.name() + ", v=" + version;
}

@Override
public Hash hash(CharSequence plainTextPassword)
{
byte[] salt = SaltGenerator.generate();
return internalHash(plainTextPassword, salt, null);
}

@Override
public Hash hash(CharSequence plainTextPassword, String salt)
{
return hash(plainTextPassword, salt, null);
}

@Override
public Hash hash(CharSequence plainTextPassword, String salt, CharSequence pepper)
{
return internalHash(plainTextPassword, Utils.fromCharSequenceToBytes(salt), pepper);
}

private Hash internalHash(CharSequence plainTextPassword, byte[] salt, CharSequence pepper)
{
byte[] password = Utils.fromCharSequenceToBytes(plainTextPassword);
long[][] blockMemory = copyOf(initialBlockMemory);

if (salt == null)
{
salt = SaltGenerator.generate();
}
initialize(password, salt, Utils.fromCharSequenceToBytes(pepper), null, blockMemory);
fillMemoryBlocks(blockMemory);
byte[] hash = ending(blockMemory);
Hash result = new Hash(this, encodeHash(hash, salt), hash, Utils.fromBytesToString(salt));
result.setPepper(pepper);
return result;
}

@Override
public boolean check(CharSequence plainTextPassword, String hashed)
{
Object[] params = decodeHash(hashed);
return check(plainTextPassword, hashed, Utils.fromBytesToString((byte[]) params[5]), null);
}

@Override
public boolean check(CharSequence plainTextPassword, String hashed, String salt, CharSequence pepper)
{
byte[] theSalt;
if (salt == null)
{
Object[] params = decodeHash(hashed);
theSalt = (byte[]) params[5];
}
else
{
theSalt = salt.getBytes(StandardCharsets.UTF_8);
}

Hash internalHash = internalHash(plainTextPassword, theSalt, pepper);
return slowEquals(internalHash.getResult(), hashed);
}

/**
* @return the memory in bytes
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/com/password4j/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ private Utils()
}

static byte[] fromCharSequenceToBytes(CharSequence charSequence)
{
return fromCharSequenceToBytes(charSequence, DEFAULT_CHARSET);
}

static byte[] fromCharSequenceToBytes(CharSequence charSequence, Charset charset)
{
if (charSequence == null)
{
return new byte[0];
}
CharsetEncoder encoder = DEFAULT_CHARSET.newEncoder();
CharsetEncoder encoder = charset.newEncoder();
int length = charSequence.length();
int arraySize = scale(length, encoder.maxBytesPerChar());
byte[] result = new byte[arraySize];
Expand Down
8 changes: 4 additions & 4 deletions src/test/com/password4j/PasswordTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -797,11 +797,11 @@ public void testScryptNonStandardParams()
@Test
public void testArgon2NonstandardParams()
{
/*
* This password hash comes from the Argon2 C reference implementation (https://github.com/P-H-C/phc-winner-argon2).
*/
// This password hash comes from the Argon2 C reference implementation (https://github.com/P-H-C/phc-winner-argon2).

final String testHash = "$argon2i$v=19$m=65536,t=2,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG";
assertTrue(Password.check("password", testHash).with(Argon2Function.getInstanceFromHash(testHash)));
Argon2Function argon2Function = Argon2Function.getInstanceFromHash(testHash);
assertTrue(Password.check("password", testHash).with(argon2Function));
}


Expand Down

0 comments on commit c9bcc24

Please sign in to comment.