1515package bcrypt_jruby ;
1616
1717import java .io .UnsupportedEncodingException ;
18-
1918import java .security .SecureRandom ;
2019
2120/**
5655 * <p>
5756 * The amount of work increases exponentially (2**log_rounds), so
5857 * each increment is twice as much work. The default log_rounds is
59- * 10, and the valid range is 4 to 31 .
58+ * 10, and the valid range is 4 to 30 .
6059 *
6160 * @author Damien Miller
6261 * @version 0.2
@@ -336,7 +335,9 @@ public class BCrypt {
336335 0xb74e6132 , 0xce77e25b , 0x578fdfe3 , 0x3ac372e6
337336 };
338337
339- // bcrypt IV: "OrpheanBeholderScryDoubt"
338+ // bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls
339+ // this "ciphertext", but it is really plaintext or an IV. We keep
340+ // the name to make code comparison easier.
340341 static private final int bf_crypt_ciphertext [] = {
341342 0x4f727068 , 0x65616e42 , 0x65686f6c ,
342343 0x64657253 , 0x63727944 , 0x6f756274
@@ -602,23 +603,24 @@ private void ekskey(byte data[], byte key[]) {
602603 * @param salt the binary salt to hash with the password
603604 * @param log_rounds the binary logarithm of the number
604605 * of rounds of hashing to apply
606+ * @param cdata the plaintext to encrypt
605607 * @return an array containing the binary hashed password
606608 */
607- private byte [] crypt_raw (byte password [], byte salt [], int log_rounds ) {
609+ public byte [] crypt_raw (byte password [], byte salt [], int log_rounds ,
610+ int cdata []) {
608611 int rounds , i , j ;
609- int cdata [] = (int [])bf_crypt_ciphertext .clone ();
610612 int clen = cdata .length ;
611613 byte ret [];
612614
613- if (log_rounds < 4 || log_rounds > 31 )
615+ if (log_rounds < 4 || log_rounds > 30 )
614616 throw new IllegalArgumentException ("Bad number of rounds" );
615617 rounds = 1 << log_rounds ;
616618 if (salt .length != BCRYPT_SALT_LEN )
617619 throw new IllegalArgumentException ("Bad salt length" );
618620
619621 init_key ();
620622 ekskey (salt , password );
621- for (i = 0 ; i < rounds ; i ++) {
623+ for (i = 0 ; i != rounds ; i ++) {
622624 key (password );
623625 key (salt );
624626 }
@@ -679,14 +681,19 @@ public static String hashpw(String password, String salt) {
679681 saltb = decode_base64 (real_salt , BCRYPT_SALT_LEN );
680682
681683 B = new BCrypt ();
682- hashed = B .crypt_raw (passwordb , saltb , rounds );
684+ hashed = B .crypt_raw (passwordb , saltb , rounds ,
685+ (int [])bf_crypt_ciphertext .clone ());
683686
684687 rs .append ("$2" );
685688 if (minor >= 'a' )
686689 rs .append (minor );
687690 rs .append ("$" );
688691 if (rounds < 10 )
689692 rs .append ("0" );
693+ if (rounds > 30 ) {
694+ throw new IllegalArgumentException (
695+ "rounds exceeds maximum (30)" );
696+ }
690697 rs .append (Integer .toString (rounds ));
691698 rs .append ("$" );
692699 rs .append (encode_base64 (saltb , saltb .length ));
@@ -712,6 +719,10 @@ public static String gensalt(int log_rounds, SecureRandom random) {
712719 rs .append ("$2a$" );
713720 if (log_rounds < 10 )
714721 rs .append ("0" );
722+ if (log_rounds > 30 ) {
723+ throw new IllegalArgumentException (
724+ "log_rounds exceeds maximum (30)" );
725+ }
715726 rs .append (Integer .toString (log_rounds ));
716727 rs .append ("$" );
717728 rs .append (encode_base64 (rnd , rnd .length ));
@@ -747,6 +758,20 @@ public static String gensalt() {
747758 * @return true if the passwords match, false otherwise
748759 */
749760 public static boolean checkpw (String plaintext , String hashed ) {
750- return (hashed .compareTo (hashpw (plaintext , hashed )) == 0 );
761+ byte hashed_bytes [];
762+ byte try_bytes [];
763+ try {
764+ String try_pw = hashpw (plaintext , hashed );
765+ hashed_bytes = hashed .getBytes ("UTF-8" );
766+ try_bytes = try_pw .getBytes ("UTF-8" );
767+ } catch (UnsupportedEncodingException uee ) {
768+ return false ;
769+ }
770+ if (hashed_bytes .length != try_bytes .length )
771+ return false ;
772+ byte ret = 0 ;
773+ for (int i = 0 ; i < try_bytes .length ; i ++)
774+ ret |= hashed_bytes [i ] ^ try_bytes [i ];
775+ return ret == 0 ;
751776 }
752777}
0 commit comments