package blowfish
-func expandKey(key []byte, c *Cipher) {
- copy(c.p[0:], p[0:])
- copy(c.s0[0:], s0[0:])
- copy(c.s1[0:], s1[0:])
- copy(c.s2[0:], s2[0:])
- copy(c.s3[0:], s3[0:])
-
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
j := 0
for i := 0; i < 18; i++ {
var d uint32
}
}
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+ j := 0
+ expandedKey := make([]uint32, 18)
+ for i := 0; i < 18; i++ {
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(key[j])&0x000000FF
+ j++
+ if j >= len(key) {
+ j = 0
+ }
+ }
+ expandedKey[i] = d
+ c.p[i] ^= d
+ }
+
+ j = 0
+ expandedSalt := make([]uint32, 18)
+ for i := 0; i < 18; i++ {
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(salt[j])&0x000000FF
+ j++
+ if j >= len(salt) {
+ j = 0
+ }
+ }
+ expandedSalt[i] = d
+ }
+
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l ^= expandedSalt[i&2]
+ r ^= expandedSalt[(i&2)+1]
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s0[i+2], c.s0[i+3] = l, r
+
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s1[i+2], c.s1[i+3] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s2[i+2], c.s2[i+3] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s3[i+2], c.s3[i+3] = l, r
+ }
+}
+
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
xl, xr := l, r
xl ^= c.p[0]
// NewCipher creates and returns a Cipher.
// The key argument should be the Blowfish key, 4 to 56 bytes.
func NewCipher(key []byte) (*Cipher, os.Error) {
+ var result Cipher
k := len(key)
if k < 4 || k > 56 {
return nil, KeySizeError(k)
}
+ initCipher(key, &result)
+ ExpandKey(key, &result)
+ return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, os.Error) {
var result Cipher
- expandKey(key, &result)
+ k := len(key)
+ if k < 4 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(key, &result)
+ expandKeyWithSalt(key, salt, &result)
return &result, nil
}
zero(c.s2[0:])
zero(c.s3[0:])
}
+
+func initCipher(key []byte, c *Cipher) {
+ copy(c.p[0:], p[0:])
+ copy(c.s0[0:], s0[0:])
+ copy(c.s1[0:], s1[0:])
+ copy(c.s2[0:], s2[0:])
+ copy(c.s3[0:], s3[0:])
+}