summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java315
1 files changed, 0 insertions, 315 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java b/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java
deleted file mode 100644
index b5f133f..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/generators/OpenBSDBCrypt.java
+++ /dev/null
@@ -1,315 +0,0 @@
-package org.bouncycastle.crypto.generators;
-
-import java.io.ByteArrayOutputStream;
-
-import org.bouncycastle.crypto.DataLengthException;
-import org.bouncycastle.util.Arrays;
-import org.bouncycastle.util.Strings;
-
-/**
- * Password hashing scheme BCrypt,
- * designed by Niels Provos and David Mazières, using the
- * String format and the Base64 encoding
- * of the reference implementation on OpenBSD
- */
-public class OpenBSDBCrypt
-{
- private static final byte[] encodingTable = // the Bcrypts encoding table for OpenBSD
- {
- (byte)'.', (byte)'/', (byte)'A', (byte)'B', (byte)'C', (byte)'D',
- (byte)'E', (byte)'F', (byte)'G', (byte)'H', (byte)'I', (byte)'J',
- (byte)'K', (byte)'L', (byte)'M', (byte)'N', (byte)'O', (byte)'P',
- (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', (byte)'V',
- (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', (byte)'a', (byte)'b',
- (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', (byte)'h',
- (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t',
- (byte)'u', (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
- (byte)'6', (byte)'7', (byte)'8', (byte)'9'
- };
- /*
- * set up the decoding table.
- */
- private static final byte[] decodingTable = new byte[128];
- private static final String version = "2a"; // previous version was not UTF-8
-
- static
- {
- for (int i = 0; i < decodingTable.length; i++)
- {
- decodingTable[i] = (byte)0xff;
- }
-
- for (int i = 0; i < encodingTable.length; i++)
- {
- decodingTable[encodingTable[i]] = (byte)i;
- }
- }
-
- public OpenBSDBCrypt()
- {
-
- }
-
- /**
- * Creates a 60 character Bcrypt String, including
- * version, cost factor, salt and hash, separated by '$'
- *
- * @param cost the cost factor, treated as an exponent of 2
- * @param salt a 16 byte salt
- * @param password the password
- * @return a 60 character Bcrypt String
- */
- private static String createBcryptString(
- byte[] password,
- byte[] salt,
- int cost)
- {
- StringBuffer sb = new StringBuffer(60);
- sb.append('$');
- sb.append(version);
- sb.append('$');
- sb.append(cost < 10 ? ("0" + cost) : Integer.toString(cost));
- sb.append('$');
- sb.append(encodeData(salt));
-
- byte[] key = BCrypt.generate(password, salt, cost);
-
- sb.append(encodeData(key));
-
- return sb.toString();
- }
-
- /**
- * Creates a 60 character Bcrypt String, including
- * version, cost factor, salt and hash, separated by '$'
- *
- * @param cost the cost factor, treated as an exponent of 2
- * @param salt a 16 byte salt
- * @param password the password
- * @return a 60 character Bcrypt String
- */
- public static String generate(
- char[] password,
- byte[] salt,
- int cost)
- {
- if (password == null)
- {
- throw new IllegalArgumentException("Password required.");
- }
- if (salt == null)
- {
- throw new IllegalArgumentException("Salt required.");
- }
- else if (salt.length != 16)
- {
- throw new DataLengthException("16 byte salt required: " + salt.length);
- }
- if (cost < 4 || cost > 31) // Minimum rounds: 16, maximum 2^31
- {
- throw new IllegalArgumentException("Invalid cost factor.");
- }
-
- byte[] psw = Strings.toUTF8ByteArray(password);
-
- // 0 termination:
-
- byte[] tmp = new byte[psw.length >= 72 ? 72 : psw.length + 1];
-
- if (tmp.length > psw.length)
- {
- System.arraycopy(psw, 0, tmp, 0, psw.length);
- }
- else
- {
- System.arraycopy(psw, 0, tmp, 0, tmp.length);
- }
-
- Arrays.fill(psw, (byte)0);
-
- String rv = createBcryptString(tmp, salt, cost);
-
- Arrays.fill(tmp, (byte)0);
-
- return rv;
- }
-
- /**
- * Checks if a password corresponds to a 60 character Bcrypt String
- *
- * @param bcryptString a 60 character Bcrypt String, including
- * version, cost factor, salt and hash,
- * separated by '$'
- * @param password the password as an array of chars
- * @return true if the password corresponds to the
- * Bcrypt String, otherwise false
- */
- public static boolean checkPassword(
- String bcryptString,
- char[] password)
- {
- // validate bcryptString:
- if (bcryptString.length() != 60)
- {
- throw new DataLengthException("Bcrypt String length: "
- + bcryptString.length() + ", 60 required.");
- }
- if (bcryptString.charAt(0) != '$'
- || bcryptString.charAt(3) != '$'
- || bcryptString.charAt(6) != '$')
- {
- throw new IllegalArgumentException("Invalid Bcrypt String format.");
- }
- if (!bcryptString.substring(1, 3).equals(version))
- {
- throw new IllegalArgumentException("Wrong Bcrypt version, 2a expected.");
- }
- int cost = 0;
- try
- {
- cost = Integer.parseInt(bcryptString.substring(4, 6));
- }
- catch (NumberFormatException nfe)
- {
- throw new IllegalArgumentException("Invalid cost factor:"
- + bcryptString.substring(4, 6));
- }
- if (cost < 4 || cost > 31)
- {
- throw new IllegalArgumentException("Invalid cost factor: "
- + cost + ", 4 < cost < 31 expected.");
- }
- // check password:
- if (password == null)
- {
- throw new IllegalArgumentException("Missing password.");
- }
- byte[] salt = decodeSaltString(
- bcryptString.substring(bcryptString.lastIndexOf('$') + 1,
- bcryptString.length() - 31));
-
- String newBcryptString = generate(password, salt, cost);
-
- return bcryptString.equals(newBcryptString);
- }
-
- /*
- * encode the input data producing a Bcrypt base 64 String.
- *
- * @param a byte representation of the salt or the password
- * @return the Bcrypt base64 String
- */
- private static String encodeData(
- byte[] data)
-
- {
- if (data.length != 24 && data.length != 16) // 192 bit key or 128 bit salt expected
- {
- throw new DataLengthException("Invalid length: " + data.length + ", 24 for key or 16 for salt expected");
- }
- boolean salt = false;
- if (data.length == 16)//salt
- {
- salt = true;
- byte[] tmp = new byte[18];// zero padding
- System.arraycopy(data, 0, tmp, 0, data.length);
- data = tmp;
- }
- else // key
- {
- data[data.length - 1] = (byte)0;
- }
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- int len = data.length;
-
- int a1, a2, a3;
- int i;
- for (i = 0; i < len; i += 3)
- {
- a1 = data[i] & 0xff;
- a2 = data[i + 1] & 0xff;
- a3 = data[i + 2] & 0xff;
-
- out.write(encodingTable[(a1 >>> 2) & 0x3f]);
- out.write(encodingTable[((a1 << 4) | (a2 >>> 4)) & 0x3f]);
- out.write(encodingTable[((a2 << 2) | (a3 >>> 6)) & 0x3f]);
- out.write(encodingTable[a3 & 0x3f]);
- }
-
- String result = Strings.fromByteArray(out.toByteArray());
- if (salt == true)// truncate padding
- {
- return result.substring(0, 22);
- }
- else
- {
- return result.substring(0, result.length() - 1);
- }
- }
-
-
- /*
- * decodes the bcrypt base 64 encoded SaltString
- *
- * @param a 22 character Bcrypt base 64 encoded String
- * @return the 16 byte salt
- * @exception DataLengthException if the length
- * of parameter is not 22
- * @exception InvalidArgumentException if the parameter
- * contains a value other than from Bcrypts base 64 encoding table
- */
- private static byte[] decodeSaltString(
- String saltString)
- {
- char[] saltChars = saltString.toCharArray();
-
- ByteArrayOutputStream out = new ByteArrayOutputStream(16);
- byte b1, b2, b3, b4;
-
- if (saltChars.length != 22)// bcrypt salt must be 22 (16 bytes)
- {
- throw new DataLengthException("Invalid base64 salt length: " + saltChars.length + " , 22 required.");
- }
-
- // check String for invalid characters:
- for (int i = 0; i < saltChars.length; i++)
- {
- int value = saltChars[i];
- if (value > 122 || value < 46 || (value > 57 && value < 65))
- {
- throw new IllegalArgumentException("Salt string contains invalid character: " + value);
- }
- }
-
- // Padding: add two '\u0000'
- char[] tmp = new char[22 + 2];
- System.arraycopy(saltChars, 0, tmp, 0, saltChars.length);
- saltChars = tmp;
-
- int len = saltChars.length;
-
- for (int i = 0; i < len; i += 4)
- {
- b1 = decodingTable[saltChars[i]];
- b2 = decodingTable[saltChars[i + 1]];
- b3 = decodingTable[saltChars[i + 2]];
- b4 = decodingTable[saltChars[i + 3]];
-
- out.write((b1 << 2) | (b2 >> 4));
- out.write((b2 << 4) | (b3 >> 2));
- out.write((b3 << 6) | b4);
- }
-
- byte[] saltBytes = out.toByteArray();
-
- // truncate:
- byte[] tmpSalt = new byte[16];
- System.arraycopy(saltBytes, 0, tmpSalt, 0, tmpSalt.length);
- saltBytes = tmpSalt;
-
- return saltBytes;
- }
-} \ No newline at end of file