Class BCryptPasswordImpl
- java.lang.Object
-
- org.wildfly.security.password.impl.AbstractPasswordImpl
-
- org.wildfly.security.password.impl.BCryptPasswordImpl
-
- All Implemented Interfaces:
Serializable
,Cloneable
,Key
,BCryptPassword
,OneWayPassword
,Password
class BCryptPasswordImpl extends AbstractPasswordImpl implements BCryptPassword
Implementation of the bcrypt password.
- Author:
- Stefan Guilhen
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
BCryptPasswordImpl.BCryptState
Class that represents the bcrypt state.private static class
BCryptPasswordImpl.CyclicByteBuffer
This class implements a cyclic byte buffer.
-
Field Summary
Fields Modifier and Type Field Description private byte[]
hash
private int
iterationCount
private static int[]
orpheanBeholderScryDoubt
private static int[]
Parray
private byte[]
salt
private static int[]
Sboxes
private static long
serialVersionUID
private static byte[]
zeroedSalt
-
Fields inherited from interface org.wildfly.security.password.interfaces.BCryptPassword
ALGORITHM_BCRYPT, BCRYPT_HASH_SIZE, BCRYPT_SALT_SIZE, DEFAULT_ITERATION_COUNT
-
-
Constructor Summary
Constructors Constructor Description BCryptPasswordImpl(byte[] hash, byte[] salt, int iterationCount)
BCryptPasswordImpl(char[] password, Charset hashCharset)
BCryptPasswordImpl(char[] password, IteratedPasswordAlgorithmSpec spec, Charset hashCharset)
BCryptPasswordImpl(char[] password, IteratedSaltedPasswordAlgorithmSpec spec, Charset hashCharset)
BCryptPasswordImpl(char[] password, SaltedPasswordAlgorithmSpec spec, Charset hashCharset)
BCryptPasswordImpl(BCryptPassword bCryptPassword)
BCryptPasswordImpl(ClearPasswordSpec clearPasswordSpec)
BCryptPasswordImpl(IteratedSaltedHashPasswordSpec passwordSpec)
BCryptPasswordImpl(SaltedHashPasswordSpec passwordSpec)
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) static byte[]
bcrypt(int cost, byte[] salt, byte[] password)
Hashes the password with the given salt and cost using the bcrypt algorithm.BCryptPasswordImpl
clone()
Creates and returns a copy of thisPassword
.(package private) <T extends KeySpec>
booleanconvertibleTo(Class<T> keySpecType)
private static BCryptPasswordImpl.BCryptState
eksBlowfishSetup(int cost, byte[] salt, byte[] key)
Performs the Blowfish expensive key schedule setup.private static void
encrypt(BCryptPasswordImpl.BCryptState state, int[] value)
Encrypt splits 64-bit blocks into two 32-bit halves, left and right.boolean
equals(Object obj)
private static void
expandKey(BCryptPasswordImpl.BCryptState state, byte[] salt, byte[] key)
Performs the expandKey step in the expensive key schedule setup.String
getAlgorithm()
byte[]
getHash()
Get the hash segment of this password.int
getIterationCount()
Get the iteration count of this password.(package private) <S extends KeySpec>
SgetKeySpec(Class<S> keySpecType)
byte[]
getSalt()
Get the salt segment of this password.int
hashCode()
private void
readObject(ObjectInputStream ignored)
(package private) boolean
verify(char[] guess)
(package private) boolean
verify(char[] guess, Charset hashCharset)
(package private) Object
writeReplace()
-
Methods inherited from class org.wildfly.security.password.impl.AbstractPasswordImpl
getEncoded, getFormat, getNormalizedPasswordBytes, getNormalizedPasswordBytes, translate
-
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface org.wildfly.security.password.interfaces.BCryptPassword
getParameterSpec, impliesParameters
-
Methods inherited from interface java.security.Key
getEncoded, getFormat
-
Methods inherited from interface org.wildfly.security.password.Password
castAndApply, castAndApply, castAs, castAs
-
-
-
-
Field Detail
-
serialVersionUID
private static final long serialVersionUID
- See Also:
- Constant Field Values
-
hash
private final byte[] hash
-
salt
private final byte[] salt
-
iterationCount
private final int iterationCount
-
Parray
private static final int[] Parray
-
Sboxes
private static final int[] Sboxes
-
orpheanBeholderScryDoubt
private static final int[] orpheanBeholderScryDoubt
-
zeroedSalt
private static final byte[] zeroedSalt
-
-
Constructor Detail
-
BCryptPasswordImpl
BCryptPasswordImpl(byte[] hash, byte[] salt, int iterationCount)
-
BCryptPasswordImpl
BCryptPasswordImpl(BCryptPassword bCryptPassword)
-
BCryptPasswordImpl
BCryptPasswordImpl(IteratedSaltedHashPasswordSpec passwordSpec)
-
BCryptPasswordImpl
BCryptPasswordImpl(SaltedHashPasswordSpec passwordSpec)
-
BCryptPasswordImpl
BCryptPasswordImpl(ClearPasswordSpec clearPasswordSpec)
-
BCryptPasswordImpl
BCryptPasswordImpl(char[] password, Charset hashCharset) throws InvalidKeySpecException
- Throws:
InvalidKeySpecException
-
BCryptPasswordImpl
BCryptPasswordImpl(char[] password, IteratedSaltedPasswordAlgorithmSpec spec, Charset hashCharset) throws InvalidKeySpecException
- Throws:
InvalidKeySpecException
-
BCryptPasswordImpl
BCryptPasswordImpl(char[] password, SaltedPasswordAlgorithmSpec spec, Charset hashCharset) throws InvalidKeySpecException
- Throws:
InvalidKeySpecException
-
BCryptPasswordImpl
BCryptPasswordImpl(char[] password, IteratedPasswordAlgorithmSpec spec, Charset hashCharset) throws InvalidKeySpecException
- Throws:
InvalidKeySpecException
-
-
Method Detail
-
getAlgorithm
public String getAlgorithm()
- Specified by:
getAlgorithm
in interfaceKey
-
getHash
public byte[] getHash()
Description copied from interface:BCryptPassword
Get the hash segment of this password.- Specified by:
getHash
in interfaceBCryptPassword
- Returns:
- the hash segment
-
getSalt
public byte[] getSalt()
Description copied from interface:BCryptPassword
Get the salt segment of this password.- Specified by:
getSalt
in interfaceBCryptPassword
- Returns:
- the salt segment
-
getIterationCount
public int getIterationCount()
Description copied from interface:BCryptPassword
Get the iteration count of this password.- Specified by:
getIterationCount
in interfaceBCryptPassword
- Returns:
- the iteration count
-
getKeySpec
<S extends KeySpec> S getKeySpec(Class<S> keySpecType) throws InvalidKeySpecException
- Specified by:
getKeySpec
in classAbstractPasswordImpl
- Throws:
InvalidKeySpecException
-
verify
boolean verify(char[] guess) throws InvalidKeyException
- Specified by:
verify
in classAbstractPasswordImpl
- Throws:
InvalidKeyException
-
verify
boolean verify(char[] guess, Charset hashCharset) throws InvalidKeyException
- Overrides:
verify
in classAbstractPasswordImpl
- Throws:
InvalidKeyException
-
convertibleTo
<T extends KeySpec> boolean convertibleTo(Class<T> keySpecType)
- Specified by:
convertibleTo
in classAbstractPasswordImpl
-
bcrypt
static byte[] bcrypt(int cost, byte[] salt, byte[] password)
Hashes the password with the given salt and cost using the bcrypt algorithm. The algorithm is defined as follows:
bcrypt(cost, salt, pwd) state <- eksBlowfishSetup(cost, salt, pwd) ctext <- "OrpheanBeholderScryDoubt" repeat(64) ctext <- EncryptECB(state, ctext) return Concatenate(cost, salt, ctext)
This implementation differs from the above algorithm in that it returns the encrypted ctext in its raw form. The
ModularCrypt
class can be used to obtain the hashed password in its crypt string format (i.e. $2a$cost$encodedSaltencodedPassword).It is important to note that bcrypt has a limitation when it comes to the password size: only the first 72 bytes of the password are involved in the key schedule phase, so large keys that share the same first 72 bytes will produce the same hash.
- Parameters:
cost
- the cost of the bcrypt algorithm. It represents the log value of the number of rounds to be applied. Thus, a cost value of 6 means that a total of 2^6 = 64 rounds will be applied, while a cost value of 20 means that a total of 2^20 = 1.048.576 rounds will be applied. It must be a value between 4 and 31 (inclusive).salt
- the 128-bit salt to be used. It is represented by a 16-byte array.password
- the password to be hashed, in its byte array form.- Returns:
- a byte[] containing the hashed password.
-
eksBlowfishSetup
private static BCryptPasswordImpl.BCryptState eksBlowfishSetup(int cost, byte[] salt, byte[] key)
Performs the Blowfish expensive key schedule setup. This phase is defined as follows:
eksBlowfishSetup(cost, salt, key) state <- InitState(); state <- expandKey(state, salt, key) repeat(2^cost) state <- expandKey(state, 0, key) state <- expandKey(state, 0, salt) return state
- Parameters:
cost
- the cost of the bcrypt algorithm. It represents the log value of the number of rounds to be applied. Thus, a cost value of 6 means that a total of 2^6 = 64 rounds will be applied, while a cost value of 20 means that a total of 2^20 = 1.048.576 rounds will be applied. It must be a value between 4 and 31 (inclusive).salt
- the 128-bit salt to be used. It is represented by a 16-byte array.key
- the password being hashed, in its byte array form.
-
expandKey
private static void expandKey(BCryptPasswordImpl.BCryptState state, byte[] salt, byte[] key)
Performs the expandKey step in the expensive key schedule setup. This step is defined as follows:
expandKey(state, salt, key) for(n = 1..18) P[n] <- key[32(n-1)..32n-1] ^ P[n] // treat key as cyclic. ctext <- encrypt(salt[0..63]) P[0] <- ctext[0..31] P[1] <- ctext[32..63] for(n = 1..8) ctext <- encrypt(ctext ^ salt[64(n-1)..64n-1]) // encrypt using the current key schedule and treat the salt as cyclic. P[2n] <- ctext[0..31] P[2n+1] <- ctext[32..63] for(i = 1..4] for(n = 0..127] ctext <- encrypt(ctext ^ salt[64(n-1)..64n-1]) // as above Si[2n] <- ctext[0..31] Si[2n+1] <- ctext[32..63] return state;
- Parameters:
state
- the current bcrypt state (P-array and S-boxes).salt
- the 128-bit salt to be used. It is represented by a 16-byte array.key
- the password being hashed, in its byte array form.
-
encrypt
private static void encrypt(BCryptPasswordImpl.BCryptState state, int[] value)
Encrypt splits 64-bit blocks into two 32-bit halves, left and right. The most significant half (left) is xored with subkey P[0] and used as input for function F (Feistel substitution). The result of that function is xored with the least significant half (right). The halves are then swapped and the process repeats for a total of 16 times:
L0 <- block[0..31] R0 <- block[32..63] for(i = 1..16) Ri <- Li-1 ^ P[i-1] Li <- Ri-1 ^ F(Ri)
After 16 rounds the halves are swapped again and xored with the final two subkeys:
R17 <- L16 ^ P[16] L17 <- R16 ^ P[17]
This method takes the 64-bit blocks as pairs of integers (32-bits each) in the value parameter and encrypts each pair separately. Encryption happens in place - i.e. the encrypted values are written back to the incoming array, replacing the previous values.
- Parameters:
state
- the current bcrypt state (P-array and S-boxes).value
- a int[] containing the 32-bit pairs that must be encrypted.
-
hashCode
public int hashCode()
- Specified by:
hashCode
in classAbstractPasswordImpl
-
equals
public boolean equals(Object obj)
- Specified by:
equals
in classAbstractPasswordImpl
-
readObject
private void readObject(ObjectInputStream ignored) throws NotSerializableException
- Throws:
NotSerializableException
-
writeReplace
Object writeReplace()
-
clone
public BCryptPasswordImpl clone()
Description copied from interface:Password
Creates and returns a copy of thisPassword
.- Specified by:
clone
in interfaceBCryptPassword
- Specified by:
clone
in interfaceOneWayPassword
- Specified by:
clone
in interfacePassword
- Specified by:
clone
in classAbstractPasswordImpl
- Returns:
- a copy of this
Password
.
-
-