Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I was reading the source code of several BCrypt implementations and found that two common c implementations have a difference in their base64 encoding of for the salt.

What is the effect, if any, of the differences on line 18 and line 22 of the two base64 encoding implementations below.

Original implementation

/**
 * Original BCrypt implementation
 * http://mail-index.netbsd.org/tech-crypto/2002/05/24/msg000204.html
 */
function encodeBase64_a($input) {
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $i = 0;
    $output = '';
    while (true) {
        $c1 = ord($input{$i++});
        $output .= $itoa64{$c1 >> 2};
        $c1 = ($c1 & 0x03) << 4;
        if ($i >= 16) {
            $output .= $itoa64{$c1};
            break;
        }
        $c2 = ord($input{$i++});
        $c1 |= $c2 >> 4 & 0x0f;
        $output .= $itoa64{$c1};
        $c1 = ($c2 & 0x0f) << 2;
        $c2 = ord($input{$i++});
        $c1 |= $c2 >> 6 & 0x03;
        $output .= $itoa64{$c1};
        $output .= $itoa64{$c2 & 0x3f};
    }
    return $output;
}

OpenWall implementation

/**
 * OpenWall implementation
 * crypt_blowfish-1.2
 * source: http://www.openwall.com/crypt/
 */
function encodeBase64_b($input) {
    $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $i = 0;
    $output = '';
    while (true) {
        $c1 = ord($input{$i++});
        $output .= $itoa64{$c1 >> 2};
        $c1 = ($c1 & 0x03) << 4;
        if ($i >= 16) {
            $output .= $itoa64{$c1};
            break;
        }
        $c2 = ord($input{$i++});
        $c1 |= $c2 >> 4;
        $output .= $itoa64{$c1};
        $c1 = ($c2 & 0x0f) << 2;
        $c2 = ord($input{$i++});
        $c1 |= $c2 >> 6;
        $output .= $itoa64{$c1};
        $output .= $itoa64{$c2 & 0x3f};
    }
    return $output;
}

Differences side by side:

+------+-------------------------+------------------+
| Line | Niels Provos            | OpenWall         |
+------+-------------------------+------------------+
|   18 | $c1 |= $c2 >> 4 & 0x0f; | $c1 |= $c2 >> 4; |
|      |                         |                  |
|   22 | $c1 |= $c2 >> 6 & 0x03; | $c1 |= $c2 >> 6; |
+------+-------------------------+------------------+

Do the differences have any effect? do they affect compatibility?

share|improve this question
add comment

1 Answer

up vote 3 down vote accepted

There's no difference here. Niels' implementation just goes one step further to verify that the correct bits are set/unset, by using & as a bitmask:

10010111 >> 4 = 00001001 (OpenWall's outputs this value)
0x0F = 00001111
00001001 & 00001111 = 00001001 (Niels' implementation outputs this value)

11010111 >> 6 = 00000010 (OpenWall's outputs this value)
0x03 = 00000011
00000010 & 00000011 = 00000010 (Niels' implementation outputs this value)

Notice that 0x0F masks all but the four rightmost bits, whereas 0x03 masks all but the two rightmost bits. Then consider that the shifts leave 4 and 2 bits remaining respectively, on an 8-bit value.

As such, as long as $c2 is an 8-bit value, the bitmask is unnecessary and the two implementations are equal.

share|improve this answer
    
Don't you mean "as long as $c2 is an 8-bit value"? –  David Wachtfogel Oct 15 '12 at 11:58
    
Yes, sorry. Will edit. –  Polynomial Oct 15 '12 at 12:04
    
thanks for the explaining –  Jacco Oct 15 '12 at 12:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.