khenaidoo | ab1f7bd | 2019-11-14 14:00:27 -0500 | [diff] [blame] | 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 | |
| 5 | package 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. |
| 9 | func 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. |
| 28 | func 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. |
| 71 | func 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 | |
| 115 | func 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 | |
| 138 | func 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 | } |