1
0
mirror of https://github.com/golang/go synced 2024-11-24 21:00:09 -07:00

crypto/twofish: update with rsc's comments

TBR=rsc

R=rsc
CC=berengar.lehr, golang-dev
https://golang.org/cl/4050042
This commit is contained in:
Adam Langley 2011-01-19 19:41:27 -05:00
parent 7963b04a18
commit 4a7fed4d90
2 changed files with 67 additions and 67 deletions

View File

@ -51,9 +51,9 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
var S [4 * 4]byte var S [4 * 4]byte
for i := 0; i < k; i++ { for i := 0; i < k; i++ {
// Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7] // Computes [y0 y1 y2 y3] = rs . [x0 x1 x2 x3 x4 x5 x6 x7]
for j := 0; j < 4; j++ { for j, rsRow := range rs {
for k := 0; k < 8; k++ { for k, rsVal := range rsRow {
S[4*i+j] ^= gfMult(key[8*i+k], rs[j][k], rsPolynomial) S[4*i+j] ^= gfMult(key[8*i+k], rsVal, rsPolynomial)
} }
} }
} }
@ -63,13 +63,13 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
var tmp [4]byte var tmp [4]byte
for i := byte(0); i < 20; i++ { for i := byte(0); i < 20; i++ {
// A = h(p * 2x, Me) // A = h(p * 2x, Me)
for j := 0; j < 4; j++ { for j := range tmp {
tmp[j] = 2 * i tmp[j] = 2 * i
} }
A := h(tmp[:], key, 0) A := h(tmp[:], key, 0)
// B = rolc(h(p * (2x + 1), Mo), 8) // B = rolc(h(p * (2x + 1), Mo), 8)
for j := 0; j < 4; j++ { for j := range tmp {
tmp[j] = 2*i + 1 tmp[j] = 2*i + 1
} }
B := h(tmp[:], key, 1) B := h(tmp[:], key, 1)
@ -84,21 +84,21 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
// Calculate sboxes // Calculate sboxes
switch k { switch k {
case 2: case 2:
for i := 0; i <= 255; i++ { for i := range c.s[0] {
c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0) c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][byte(i)]^S[0]]^S[4]], 0)
c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][byte(i)]^S[1]]^S[5]], 1)
c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][byte(i)]^S[2]]^S[6]], 2)
c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3) c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][byte(i)]^S[3]]^S[7]], 3)
} }
case 3: case 3:
for i := 0; i < 256; i++ { for i := range c.s[0] {
c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0) c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]], 0)
c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[1]]^S[5]]^S[9]], 1)
c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]], 2)
c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3) c.s[3][i] = mdsColumnMult(sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[3]]^S[7]]^S[11]], 3)
} }
default: default:
for i := 0; i < 256; i++ { for i := range c.s[0] {
c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0) c.s[0][i] = mdsColumnMult(sbox[1][sbox[0][sbox[0][sbox[1][sbox[1][byte(i)]^S[0]]^S[4]]^S[8]]^S[12]], 0)
c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1) c.s[1][i] = mdsColumnMult(sbox[0][sbox[0][sbox[1][sbox[1][sbox[0][byte(i)]^S[1]]^S[5]]^S[9]]^S[13]], 1)
c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2) c.s[2][i] = mdsColumnMult(sbox[1][sbox[1][sbox[0][sbox[0][sbox[0][byte(i)]^S[2]]^S[6]]^S[10]]^S[14]], 2)
@ -112,10 +112,10 @@ func NewCipher(key []byte) (*Cipher, os.Error) {
// Reset zeros the key data, so that it will no longer appear in the process's // Reset zeros the key data, so that it will no longer appear in the process's
// memory. // memory.
func (c *Cipher) Reset() { func (c *Cipher) Reset() {
for i := 0; i < 40; i++ { for i := range c.k {
c.k[i] = 0 c.k[i] = 0
} }
for i := 0; i < 4; i++ { for i := range c.s {
for j := 0; j < 265; j++ { for j := 0; j < 265; j++ {
c.s[i][j] = 0 c.s[i][j] = 0
} }
@ -213,7 +213,7 @@ func gfMult(a, b byte, p uint32) byte {
return byte(result) return byte(result)
} }
// mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS . [x0] // mdsColumnMult calculates y{col} where [y0 y1 y2 y3] = MDS · [x0]
func mdsColumnMult(in byte, col int) uint32 { func mdsColumnMult(in byte, col int) uint32 {
mul01 := in mul01 := in
mul5B := gfMult(in, 0x5B, mdsPolynomial) mul5B := gfMult(in, 0x5B, mdsPolynomial)
@ -236,7 +236,7 @@ func mdsColumnMult(in byte, col int) uint32 {
// h implements the S-box generation function. See [TWOFISH] 4.3.5 // h implements the S-box generation function. See [TWOFISH] 4.3.5
func h(in, key []byte, offset int) uint32 { func h(in, key []byte, offset int) uint32 {
var y [4]byte var y [4]byte
for x := 0; x < 4; x++ { for x := range y {
y[x] = in[x] y[x] = in[x]
} }
switch len(key) / 8 { switch len(key) / 8 {
@ -260,7 +260,7 @@ func h(in, key []byte, offset int) uint32 {
} }
// [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] // [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3]
var mdsMult uint32 var mdsMult uint32
for i := 0; i < 4; i++ { for i := range y {
mdsMult ^= mdsColumnMult(y[i], i) mdsMult ^= mdsColumnMult(y[i], i)
} }
return mdsMult return mdsMult
@ -270,42 +270,42 @@ func h(in, key []byte, offset int) uint32 {
// Note that for amounts of data larger than a block, // Note that for amounts of data larger than a block,
// it is not safe to just call Encrypt on successive blocks; // it is not safe to just call Encrypt on successive blocks;
// instead, use an encryption mode like CBC (see crypto/block/cbc.go). // instead, use an encryption mode like CBC (see crypto/block/cbc.go).
func (skey *Cipher) Encrypt(dst, src []byte) { func (c *Cipher) Encrypt(dst, src []byte) {
S1 := skey.s[0] S1 := c.s[0]
S2 := skey.s[1] S2 := c.s[1]
S3 := skey.s[2] S3 := c.s[2]
S4 := skey.s[3] S4 := c.s[3]
// Load input // Load input
a := load32l(src[0:4]) ia := load32l(src[0:4])
b := load32l(src[4:8]) ib := load32l(src[4:8])
c := load32l(src[8:12]) ic := load32l(src[8:12])
d := load32l(src[12:16]) id := load32l(src[12:16])
// Pre-whitening // Pre-whitening
a ^= skey.k[0] ia ^= c.k[0]
b ^= skey.k[1] ib ^= c.k[1]
c ^= skey.k[2] ic ^= c.k[2]
d ^= skey.k[3] id ^= c.k[3]
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
k := skey.k[8+i*4 : 12+i*4] k := c.k[8+i*4 : 12+i*4]
t2 := S2[byte(b)] ^ S3[byte(b>>8)] ^ S4[byte(b>>16)] ^ S1[byte(b>>24)] t2 := S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
t1 := S1[byte(a)] ^ S2[byte(a>>8)] ^ S3[byte(a>>16)] ^ S4[byte(a>>24)] + t2 t1 := S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
c = ror(c^(t1+k[0]), 1) ic = ror(ic^(t1+k[0]), 1)
d = rol(d, 1) ^ (t2 + t1 + k[1]) id = rol(id, 1) ^ (t2 + t1 + k[1])
t2 = S2[byte(d)] ^ S3[byte(d>>8)] ^ S4[byte(d>>16)] ^ S1[byte(d>>24)] t2 = S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
t1 = S1[byte(c)] ^ S2[byte(c>>8)] ^ S3[byte(c>>16)] ^ S4[byte(c>>24)] + t2 t1 = S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
a = ror(a^(t1+k[2]), 1) ia = ror(ia^(t1+k[2]), 1)
b = rol(b, 1) ^ (t2 + t1 + k[3]) ib = rol(ib, 1) ^ (t2 + t1 + k[3])
} }
// Output with "undo last swap" // Output with "undo last swap"
ta := c ^ skey.k[4] ta := ic ^ c.k[4]
tb := d ^ skey.k[5] tb := id ^ c.k[5]
tc := a ^ skey.k[6] tc := ia ^ c.k[6]
td := b ^ skey.k[7] td := ib ^ c.k[7]
store32l(dst[0:4], ta) store32l(dst[0:4], ta)
store32l(dst[4:8], tb) store32l(dst[4:8], tb)
@ -314,11 +314,11 @@ func (skey *Cipher) Encrypt(dst, src []byte) {
} }
// Decrypt decrypts a 16-byte block from src to dst, which may overlap. // Decrypt decrypts a 16-byte block from src to dst, which may overlap.
func (skey *Cipher) Decrypt(dst, src []byte) { func (c *Cipher) Decrypt(dst, src []byte) {
S1 := skey.s[0] S1 := c.s[0]
S2 := skey.s[1] S2 := c.s[1]
S3 := skey.s[2] S3 := c.s[2]
S4 := skey.s[3] S4 := c.s[3]
// Load input // Load input
ta := load32l(src[0:4]) ta := load32l(src[0:4])
@ -327,32 +327,32 @@ func (skey *Cipher) Decrypt(dst, src []byte) {
td := load32l(src[12:16]) td := load32l(src[12:16])
// Undo undo final swap // Undo undo final swap
a := tc ^ skey.k[6] ia := tc ^ c.k[6]
b := td ^ skey.k[7] ib := td ^ c.k[7]
c := ta ^ skey.k[4] ic := ta ^ c.k[4]
d := tb ^ skey.k[5] id := tb ^ c.k[5]
for i := 8; i > 0; i-- { for i := 8; i > 0; i-- {
k := skey.k[4+i*4 : 8+i*4] k := c.k[4+i*4 : 8+i*4]
t2 := S2[byte(d)] ^ S3[byte(d>>8)] ^ S4[byte(d>>16)] ^ S1[byte(d>>24)] t2 := S2[byte(id)] ^ S3[byte(id>>8)] ^ S4[byte(id>>16)] ^ S1[byte(id>>24)]
t1 := S1[byte(c)] ^ S2[byte(c>>8)] ^ S3[byte(c>>16)] ^ S4[byte(c>>24)] + t2 t1 := S1[byte(ic)] ^ S2[byte(ic>>8)] ^ S3[byte(ic>>16)] ^ S4[byte(ic>>24)] + t2
a = rol(a, 1) ^ (t1 + k[2]) ia = rol(ia, 1) ^ (t1 + k[2])
b = ror(b^(t2+t1+k[3]), 1) ib = ror(ib^(t2+t1+k[3]), 1)
t2 = S2[byte(b)] ^ S3[byte(b>>8)] ^ S4[byte(b>>16)] ^ S1[byte(b>>24)] t2 = S2[byte(ib)] ^ S3[byte(ib>>8)] ^ S4[byte(ib>>16)] ^ S1[byte(ib>>24)]
t1 = S1[byte(a)] ^ S2[byte(a>>8)] ^ S3[byte(a>>16)] ^ S4[byte(a>>24)] + t2 t1 = S1[byte(ia)] ^ S2[byte(ia>>8)] ^ S3[byte(ia>>16)] ^ S4[byte(ia>>24)] + t2
c = rol(c, 1) ^ (t1 + k[0]) ic = rol(ic, 1) ^ (t1 + k[0])
d = ror(d^(t2+t1+k[1]), 1) id = ror(id^(t2+t1+k[1]), 1)
} }
// Undo pre-whitening // Undo pre-whitening
a ^= skey.k[0] ia ^= c.k[0]
b ^= skey.k[1] ib ^= c.k[1]
c ^= skey.k[2] ic ^= c.k[2]
d ^= skey.k[3] id ^= c.k[3]
store32l(dst[0:4], a) store32l(dst[0:4], ia)
store32l(dst[4:8], b) store32l(dst[4:8], ib)
store32l(dst[8:12], c) store32l(dst[8:12], ic)
store32l(dst[12:16], d) store32l(dst[12:16], id)
} }

View File

@ -37,8 +37,8 @@ func genSbox(qi int, x byte) byte {
} }
func TestSbox(t *testing.T) { func TestSbox(t *testing.T) {
for n := 0; n < 2; n++ { for n := range sbox {
for m := 0; m < 256; m++ { for m := range sbox[n] {
if genSbox(n, byte(m)) != sbox[n][m] { if genSbox(n, byte(m)) != sbox[n][m] {
t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m))) t.Errorf("#%d|%d: sbox value = %d want %d", n, m, sbox[n][m], genSbox(n, byte(m)))
} }