main
Raw Download raw file
  1// Copyright 2010 The Go Authors. All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5package blowfish
  6
  7// getNextWord returns the next big-endian uint32 value from the byte slice
  8// at the given position in a circular manner, updating the position.
  9func getNextWord(b []byte, pos *int) uint32 {
 10	var w uint32
 11	j := *pos
 12	for i := 0; i < 4; i++ {
 13		w = w<<8 | uint32(b[j])
 14		j++
 15		if j >= len(b) {
 16			j = 0
 17		}
 18	}
 19	*pos = j
 20	return w
 21}
 22
 23// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
 24// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
 25// pi and substitution tables for calls to Encrypt. This is used, primarily,
 26// by the bcrypt package to reuse the Blowfish key schedule during its
 27// set up. It's unlikely that you need to use this directly.
 28func ExpandKey(key []byte, c *Cipher) {
 29	j := 0
 30	for i := 0; i < 18; i++ {
 31		// Using inlined getNextWord for performance.
 32		var d uint32
 33		for k := 0; k < 4; k++ {
 34			d = d<<8 | uint32(key[j])
 35			j++
 36			if j >= len(key) {
 37				j = 0
 38			}
 39		}
 40		c.p[i] ^= d
 41	}
 42
 43	var l, r uint32
 44	for i := 0; i < 18; i += 2 {
 45		l, r = encryptBlock(l, r, c)
 46		c.p[i], c.p[i+1] = l, r
 47	}
 48
 49	for i := 0; i < 256; i += 2 {
 50		l, r = encryptBlock(l, r, c)
 51		c.s0[i], c.s0[i+1] = l, r
 52	}
 53	for i := 0; i < 256; i += 2 {
 54		l, r = encryptBlock(l, r, c)
 55		c.s1[i], c.s1[i+1] = l, r
 56	}
 57	for i := 0; i < 256; i += 2 {
 58		l, r = encryptBlock(l, r, c)
 59		c.s2[i], c.s2[i+1] = l, r
 60	}
 61	for i := 0; i < 256; i += 2 {
 62		l, r = encryptBlock(l, r, c)
 63		c.s3[i], c.s3[i+1] = l, r
 64	}
 65}
 66
 67// This is similar to ExpandKey, but folds the salt during the key
 68// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
 69// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
 70// and specializing it here is useful.
 71func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
 72	j := 0
 73	for i := 0; i < 18; i++ {
 74		c.p[i] ^= getNextWord(key, &j)
 75	}
 76
 77	j = 0
 78	var l, r uint32
 79	for i := 0; i < 18; i += 2 {
 80		l ^= getNextWord(salt, &j)
 81		r ^= getNextWord(salt, &j)
 82		l, r = encryptBlock(l, r, c)
 83		c.p[i], c.p[i+1] = l, r
 84	}
 85
 86	for i := 0; i < 256; i += 2 {
 87		l ^= getNextWord(salt, &j)
 88		r ^= getNextWord(salt, &j)
 89		l, r = encryptBlock(l, r, c)
 90		c.s0[i], c.s0[i+1] = l, r
 91	}
 92
 93	for i := 0; i < 256; i += 2 {
 94		l ^= getNextWord(salt, &j)
 95		r ^= getNextWord(salt, &j)
 96		l, r = encryptBlock(l, r, c)
 97		c.s1[i], c.s1[i+1] = l, r
 98	}
 99
100	for i := 0; i < 256; i += 2 {
101		l ^= getNextWord(salt, &j)
102		r ^= getNextWord(salt, &j)
103		l, r = encryptBlock(l, r, c)
104		c.s2[i], c.s2[i+1] = l, r
105	}
106
107	for i := 0; i < 256; i += 2 {
108		l ^= getNextWord(salt, &j)
109		r ^= getNextWord(salt, &j)
110		l, r = encryptBlock(l, r, c)
111		c.s3[i], c.s3[i+1] = l, r
112	}
113}
114
115func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
116	xl, xr := l, r
117	xl ^= c.p[0]
118	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
119	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
120	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
121	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
122	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
123	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
124	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
125	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
126	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
127	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
128	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
129	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
130	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
131	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
132	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
133	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
134	xr ^= c.p[17]
135	return xr, xl
136}
137
138func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
139	xl, xr := l, r
140	xl ^= c.p[17]
141	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
142	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
143	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
144	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
145	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
146	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
147	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
148	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
149	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
150	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
151	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
152	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
153	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
154	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
155	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
156	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
157	xr ^= c.p[0]
158	return xr, xl
159}