mirror of
https://github.com/HACKERALERT/Picocrypt.git
synced 2024-06-02 18:34:43 +12:00
120 lines
3.2 KiB
Go
120 lines
3.2 KiB
Go
// 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 serpent implements the Serpent block cipher
|
|
// submitted to the AES challenge. Serpent was designed by
|
|
// Ross Anderson, Eli Biham und Lars Knudsen.
|
|
// The block cipher takes a 128, 192 or 256 bit key and
|
|
// has a block size of 128 bit.
|
|
package serpent // import "github.com/aead/serpent"
|
|
|
|
import (
|
|
"crypto/cipher"
|
|
"errors"
|
|
)
|
|
|
|
// BlockSize is the serpent block size in bytes.
|
|
const BlockSize = 16
|
|
|
|
const phi = 0x9e3779b9 // The Serpent phi constant (sqrt(5) - 1) * 2**31
|
|
|
|
var errKeySize = errors.New("invalid key size")
|
|
|
|
// NewCipher returns a new cipher.Block implementing the serpent block cipher.
|
|
// The key argument must be 128, 192 or 256 bit (16, 24, 32 byte).
|
|
func NewCipher(key []byte) (cipher.Block, error) {
|
|
if k := len(key); k != 16 && k != 24 && k != 32 {
|
|
return nil, errKeySize
|
|
}
|
|
s := &subkeys{}
|
|
s.keySchedule(key)
|
|
return s, nil
|
|
}
|
|
|
|
// The 132 32 bit subkeys of serpent
|
|
type subkeys [132]uint32
|
|
|
|
func (s *subkeys) BlockSize() int { return BlockSize }
|
|
|
|
func (s *subkeys) Encrypt(dst, src []byte) {
|
|
if len(src) < BlockSize {
|
|
panic("src buffer to small")
|
|
}
|
|
if len(dst) < BlockSize {
|
|
panic("dst buffer to small")
|
|
}
|
|
encryptBlock(dst, src, s)
|
|
}
|
|
|
|
func (s *subkeys) Decrypt(dst, src []byte) {
|
|
if len(src) < BlockSize {
|
|
panic("src buffer to small")
|
|
}
|
|
if len(dst) < BlockSize {
|
|
panic("dst buffer to small")
|
|
}
|
|
decryptBlock(dst, src, s)
|
|
}
|
|
|
|
// The key schedule of serpent.
|
|
func (s *subkeys) keySchedule(key []byte) {
|
|
var k [16]uint32
|
|
j := 0
|
|
for i := 0; i+4 <= len(key); i += 4 {
|
|
k[j] = uint32(key[i]) | uint32(key[i+1])<<8 | uint32(key[i+2])<<16 | uint32(key[i+3])<<24
|
|
j++
|
|
}
|
|
if j < 8 {
|
|
k[j] = 1
|
|
}
|
|
|
|
for i := 8; i < 16; i++ {
|
|
x := k[i-8] ^ k[i-5] ^ k[i-3] ^ k[i-1] ^ phi ^ uint32(i-8)
|
|
k[i] = (x << 11) | (x >> 21)
|
|
s[i-8] = k[i]
|
|
}
|
|
for i := 8; i < 132; i++ {
|
|
x := s[i-8] ^ s[i-5] ^ s[i-3] ^ s[i-1] ^ phi ^ uint32(i)
|
|
s[i] = (x << 11) | (x >> 21)
|
|
}
|
|
|
|
sb3(&s[0], &s[1], &s[2], &s[3])
|
|
sb2(&s[4], &s[5], &s[6], &s[7])
|
|
sb1(&s[8], &s[9], &s[10], &s[11])
|
|
sb0(&s[12], &s[13], &s[14], &s[15])
|
|
sb7(&s[16], &s[17], &s[18], &s[19])
|
|
sb6(&s[20], &s[21], &s[22], &s[23])
|
|
sb5(&s[24], &s[25], &s[26], &s[27])
|
|
sb4(&s[28], &s[29], &s[30], &s[31])
|
|
|
|
sb3(&s[32], &s[33], &s[34], &s[35])
|
|
sb2(&s[36], &s[37], &s[38], &s[39])
|
|
sb1(&s[40], &s[41], &s[42], &s[43])
|
|
sb0(&s[44], &s[45], &s[46], &s[47])
|
|
sb7(&s[48], &s[49], &s[50], &s[51])
|
|
sb6(&s[52], &s[53], &s[54], &s[55])
|
|
sb5(&s[56], &s[57], &s[58], &s[59])
|
|
sb4(&s[60], &s[61], &s[62], &s[63])
|
|
|
|
sb3(&s[64], &s[65], &s[66], &s[67])
|
|
sb2(&s[68], &s[69], &s[70], &s[71])
|
|
sb1(&s[72], &s[73], &s[74], &s[75])
|
|
sb0(&s[76], &s[77], &s[78], &s[79])
|
|
sb7(&s[80], &s[81], &s[82], &s[83])
|
|
sb6(&s[84], &s[85], &s[86], &s[87])
|
|
sb5(&s[88], &s[89], &s[90], &s[91])
|
|
sb4(&s[92], &s[93], &s[94], &s[95])
|
|
|
|
sb3(&s[96], &s[97], &s[98], &s[99])
|
|
sb2(&s[100], &s[101], &s[102], &s[103])
|
|
sb1(&s[104], &s[105], &s[106], &s[107])
|
|
sb0(&s[108], &s[109], &s[110], &s[111])
|
|
sb7(&s[112], &s[113], &s[114], &s[115])
|
|
sb6(&s[116], &s[117], &s[118], &s[119])
|
|
sb5(&s[120], &s[121], &s[122], &s[123])
|
|
sb4(&s[124], &s[125], &s[126], &s[127])
|
|
|
|
sb3(&s[128], &s[129], &s[130], &s[131])
|
|
}
|