You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
5.4 KiB

// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
package threefish
func (t *threefish256) Encrypt(dst, src []byte) {
var block [4]uint64
bytesToBlock256(&block, src)
Encrypt256(&block, &(t.keys), &(t.tweak))
block256ToBytes(dst, &block)
}
func (t *threefish256) Decrypt(dst, src []byte) {
var block [4]uint64
bytesToBlock256(&block, src)
Decrypt256(&block, &(t.keys), &(t.tweak))
block256ToBytes(dst, &block)
}
func newCipher256(tweak *[TweakSize]byte, key []byte) *threefish256 {
c := new(threefish256)
c.tweak[0] = uint64(tweak[0]) | uint64(tweak[1])<<8 | uint64(tweak[2])<<16 | uint64(tweak[3])<<24 |
uint64(tweak[4])<<32 | uint64(tweak[5])<<40 | uint64(tweak[6])<<48 | uint64(tweak[7])<<56
c.tweak[1] = uint64(tweak[8]) | uint64(tweak[9])<<8 | uint64(tweak[10])<<16 | uint64(tweak[11])<<24 |
uint64(tweak[12])<<32 | uint64(tweak[13])<<40 | uint64(tweak[14])<<48 | uint64(tweak[15])<<56
c.tweak[2] = c.tweak[0] ^ c.tweak[1]
for i := range c.keys[:4] {
j := i * 8
c.keys[i] = uint64(key[j]) | uint64(key[j+1])<<8 | uint64(key[j+2])<<16 | uint64(key[j+3])<<24 |
uint64(key[j+4])<<32 | uint64(key[j+5])<<40 | uint64(key[j+6])<<48 | uint64(key[j+7])<<56
}
c.keys[4] = C240 ^ c.keys[0] ^ c.keys[1] ^ c.keys[2] ^ c.keys[3]
return c
}
// Encrypt256 encrypts the 4 words of block using the expanded 256 bit key and
// the 128 bit tweak. The keys[4] must be keys[0] xor keys[1] xor ... keys[3] xor C240.
// The tweak[2] must be tweak[0] xor tweak[1].
func Encrypt256(block *[4]uint64, keys *[5]uint64, tweak *[3]uint64) {
b0, b1, b2, b3 := block[0], block[1], block[2], block[3]
for r := 0; r < 17; r++ {
b0 += keys[r%5]
b1 += keys[(r+1)%5] + tweak[r%3]
b2 += keys[(r+2)%5] + tweak[(r+1)%3]
b3 += keys[(r+3)%5] + uint64(r)
b0 += b1
b1 = ((b1 << 14) | (b1 >> (64 - 14))) ^ b0
b2 += b3
b3 = ((b3 << 16) | (b3 >> (64 - 16))) ^ b2
b0 += b3
b3 = ((b3 << 52) | (b3 >> (64 - 52))) ^ b0
b2 += b1
b1 = ((b1 << 57) | (b1 >> (64 - 57))) ^ b2
b0 += b1
b1 = ((b1 << 23) | (b1 >> (64 - 23))) ^ b0
b2 += b3
b3 = ((b3 << 40) | (b3 >> (64 - 40))) ^ b2
b0 += b3
b3 = ((b3 << 5) | (b3 >> (64 - 5))) ^ b0
b2 += b1
b1 = ((b1 << 37) | (b1 >> (64 - 37))) ^ b2
r++
b0 += keys[r%5]
b1 += keys[(r+1)%5] + tweak[r%3]
b2 += keys[(r+2)%5] + tweak[(r+1)%3]
b3 += keys[(r+3)%5] + uint64(r)
b0 += b1
b1 = ((b1 << 25) | (b1 >> (64 - 25))) ^ b0
b2 += b3
b3 = ((b3 << 33) | (b3 >> (64 - 33))) ^ b2
b0 += b3
b3 = ((b3 << 46) | (b3 >> (64 - 46))) ^ b0
b2 += b1
b1 = ((b1 << 12) | (b1 >> (64 - 12))) ^ b2
b0 += b1
b1 = ((b1 << 58) | (b1 >> (64 - 58))) ^ b0
b2 += b3
b3 = ((b3 << 22) | (b3 >> (64 - 22))) ^ b2
b0 += b3
b3 = ((b3 << 32) | (b3 >> (64 - 32))) ^ b0
b2 += b1
b1 = ((b1 << 32) | (b1 >> (64 - 32))) ^ b2
}
b0 += keys[3]
b1 += keys[4] + tweak[0]
b2 += keys[0] + tweak[1]
b3 += keys[1] + uint64(18)
block[0], block[1], block[2], block[3] = b0, b1, b2, b3
}
// Decrypt256 decrypts the 4 words of block using the expanded 256 bit key and
// the 128 bit tweak. The keys[4] must be keys[0] xor keys[1] xor ... keys[3] xor C240.
// The tweak[2] must be tweak[0] xor tweak[1].
func Decrypt256(block *[4]uint64, keys *[5]uint64, tweak *[3]uint64) {
b0, b1, b2, b3 := block[0], block[1], block[2], block[3]
var tmp uint64
for r := 18; r > 1; r-- {
b0 -= keys[r%5]
b1 -= keys[(r+1)%5] + tweak[r%3]
b2 -= keys[(r+2)%5] + tweak[(r+1)%3]
b3 -= keys[(r+3)%5] + uint64(r)
tmp = b1 ^ b2
b1 = (tmp >> 32) | (tmp << (64 - 32))
b2 -= b1
tmp = b3 ^ b0
b3 = (tmp >> 32) | (tmp << (64 - 32))
b0 -= b3
tmp = b3 ^ b2
b3 = (tmp >> 22) | (tmp << (64 - 22))
b2 -= b3
tmp = b1 ^ b0
b1 = (tmp >> 58) | (tmp << (64 - 58))
b0 -= b1
tmp = b1 ^ b2
b1 = (tmp >> 12) | (tmp << (64 - 12))
b2 -= b1
tmp = b3 ^ b0
b3 = (tmp >> 46) | (tmp << (64 - 46))
b0 -= b3
tmp = b3 ^ b2
b3 = (tmp >> 33) | (tmp << (64 - 33))
b2 -= b3
tmp = b1 ^ b0
b1 = (tmp >> 25) | (tmp << (64 - 25))
b0 -= b1
r--
b0 -= keys[r%5]
b1 -= keys[(r+1)%5] + tweak[r%3]
b2 -= keys[(r+2)%5] + tweak[(r+1)%3]
b3 -= keys[(r+3)%5] + uint64(r)
tmp = b1 ^ b2
b1 = (tmp >> 37) | (tmp << (64 - 37))
b2 -= b1
tmp = b3 ^ b0
b3 = (tmp >> 5) | (tmp << (64 - 5))
b0 -= b3
tmp = b3 ^ b2
b3 = (tmp >> 40) | (tmp << (64 - 40))
b2 -= b3
tmp = b1 ^ b0
b1 = (tmp >> 23) | (tmp << (64 - 23))
b0 -= b1
tmp = b1 ^ b2
b1 = (tmp >> 57) | (tmp << (64 - 57))
b2 -= b1
tmp = b3 ^ b0
b3 = (tmp >> 52) | (tmp << (64 - 52))
b0 -= b3
tmp = b3 ^ b2
b3 = (tmp >> 16) | (tmp << (64 - 16))
b2 -= b3
tmp = b1 ^ b0
b1 = (tmp >> 14) | (tmp << (64 - 14))
b0 -= b1
}
b0 -= keys[0]
b1 -= keys[1] + tweak[0]
b2 -= keys[2] + tweak[1]
b3 -= keys[3]
block[0], block[1], block[2], block[3] = b0, b1, b2, b3
}
// UBI256 does a Threefish256 encryption of the given block using
// the chain values hVal and the tweak.
// The chain values are updated through hVal[i] = block[i] ^ Enc(block)[i]
func UBI256(block *[4]uint64, hVal *[5]uint64, tweak *[3]uint64) {
b0, b1, b2, b3 := block[0], block[1], block[2], block[3]
hVal[4] = C240 ^ hVal[0] ^ hVal[1] ^ hVal[2] ^ hVal[3]
tweak[2] = tweak[0] ^ tweak[1]
Encrypt256(block, hVal, tweak)
hVal[0] = block[0] ^ b0
hVal[1] = block[1] ^ b1
hVal[2] = block[2] ^ b2
hVal[3] = block[3] ^ b3
}