Skip to content

Commit

Permalink
更新
Browse files Browse the repository at this point in the history
  • Loading branch information
deatil committed May 13, 2024
1 parent bb78d27 commit 75091df
Show file tree
Hide file tree
Showing 22 changed files with 271 additions and 222 deletions.
42 changes: 10 additions & 32 deletions pkg/lakego-pkg/go-cryptobin/cipher/ascon/ascon.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,28 @@ const (
iv128a uint64 = 0x80800c0800000000 // Ascon-128a
)

var errOpen = errors.New("ascon: message authentication failed")

const (
// BlockSize128a is the size in bytes of an ASCON-128a block.
BlockSize128a = 16

// BlockSize128 is the size in bytes of an ASCON-128 block.
BlockSize128 = 8

// KeySize is the size in bytes of ASCON-128 and ASCON-128a
// keys.
KeySize = 16

// NonceSize is the size in bytes of ASCON-128 and ASCON-128a
// nonces.
NonceSize = 16

// TagSize is the size in bytes of ASCON-128 and ASCON-128a
// authenticators.
TagSize = 16
)

var errOpen = errors.New("cryptobin/ascon: message authentication failed")

type ascon struct {
k0, k1 uint64
iv uint64
Expand All @@ -45,21 +49,8 @@ type ascon struct {
// [ascon]: https://ascon.iaik.tugraz.at
//

// New128 creates a 128-bit ASCON-128 AEAD.
//
// ASCON-128 provides lower throughput but increased robustness
// against partial or full state recovery compared to ASCON-128a.
//
// Each unique key can encrypt a maximum 2^68 bytes (i.e., 2^64
// plaintext and associated data blocks). Nonces must never be
// reused with the same key. Violating either of these
// constraints compromises the security of the algorithm.
//
// There are no other constraints on the composition of the
// nonce. For example, the nonce can be a counter.
//
// Refer to ASCON's documentation for more information.
func New128(key []byte) (cipher.AEAD, error) {
// NewCipher creates a 128-bit ASCON-128 AEAD.
func NewCipher(key []byte) (cipher.AEAD, error) {
if len(key) != KeySize {
return nil, errors.New("cryptobin/ascon: bad key length")
}
Expand All @@ -71,21 +62,8 @@ func New128(key []byte) (cipher.AEAD, error) {
}, nil
}

// New128a creates a 128-bit ASCON-128a AEAD.
//
// ASCON-128a provides higher throughput but reduced robustness
// against partial or full state recovery compared to ASCON-128.
//
// Each unique key can encrypt a maximum 2^68 bytes (i.e., 2^64
// plaintext and associated data blocks). Nonces must never be
// reused with the same key. Violating either of these
// constraints compromises the security of the algorithm.
//
// There are no other constraints on the composition of the
// nonce. For example, the nonce can be a counter.
//
// Refer to ASCON's documentation for more information.
func New128a(key []byte) (cipher.AEAD, error) {
// NewCiphera creates a 128-bit ASCON-128a AEAD.
func NewCiphera(key []byte) (cipher.AEAD, error) {
if len(key) != KeySize {
return nil, errors.New("cryptobin/ascon: bad key length")
}
Expand Down
20 changes: 10 additions & 10 deletions pkg/lakego-pkg/go-cryptobin/cipher/ascon/ascon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ func TestPermute(t *testing.T) {
}

func TestVectors128(t *testing.T) {
testVectors(t, New128, filepath.Join("testdata", "vectors_128.txt"))
testVectors(t, NewCipher, filepath.Join("testdata", "vectors_128.txt"))
}

func TestVectors128a(t *testing.T) {
testVectors(t, New128a, filepath.Join("testdata", "vectors_128a.txt"))
testVectors(t, NewCiphera, filepath.Join("testdata", "vectors_128a.txt"))
}

func testVectors(t *testing.T, fn func([]byte) (cipher.AEAD, error), path string) {
Expand Down Expand Up @@ -108,35 +108,35 @@ func testVectors(t *testing.T, fn func([]byte) (cipher.AEAD, error), path string
}

func BenchmarkSeal1K_128a(b *testing.B) {
benchmarkSeal(b, New128a, make([]byte, 1024))
benchmarkSeal(b, NewCiphera, make([]byte, 1024))
}

func BenchmarkOpen1K_128a(b *testing.B) {
benchmarkOpen(b, New128a, make([]byte, 1024))
benchmarkOpen(b, NewCiphera, make([]byte, 1024))
}

func BenchmarkSeal8K_128a(b *testing.B) {
benchmarkSeal(b, New128a, make([]byte, 8*1024))
benchmarkSeal(b, NewCiphera, make([]byte, 8*1024))
}

func BenchmarkOpen8K_128a(b *testing.B) {
benchmarkOpen(b, New128a, make([]byte, 8*1024))
benchmarkOpen(b, NewCiphera, make([]byte, 8*1024))
}

func BenchmarkSeal1K_128(b *testing.B) {
benchmarkSeal(b, New128, make([]byte, 1024))
benchmarkSeal(b, NewCipher, make([]byte, 1024))
}

func BenchmarkOpen1K_128(b *testing.B) {
benchmarkOpen(b, New128, make([]byte, 1024))
benchmarkOpen(b, NewCipher, make([]byte, 1024))
}

func BenchmarkSeal8K_128(b *testing.B) {
benchmarkSeal(b, New128, make([]byte, 8*1024))
benchmarkSeal(b, NewCipher, make([]byte, 8*1024))
}

func BenchmarkOpen8K_128(b *testing.B) {
benchmarkOpen(b, New128, make([]byte, 8*1024))
benchmarkOpen(b, NewCipher, make([]byte, 8*1024))
}

func benchmarkSeal(b *testing.B, fn func([]byte) (cipher.AEAD, error), buf []byte) {
Expand Down
58 changes: 26 additions & 32 deletions pkg/lakego-pkg/go-cryptobin/cipher/rabbitio/rabbit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@ import (
"errors"
"math/bits"
"crypto/cipher"
"encoding/binary"

"github.com/deatil/go-cryptobin/tool/alias"
)

var (
invalidKeyLenErr = errors.New("cryptobin/rabbitio: key must be 16 byte len, not more not less")
invalidIVXLenErr = errors.New("cryptobin/rabbitio: iv must be 8 byte len or nothing (zero) at all")
errInvalidKeyLen = errors.New("cryptobin/rabbitio: key must be 16 byte len, not more not less")
errInvalidIVXLen = errors.New("cryptobin/rabbitio: iv must be 8 byte len or nothing (zero) at all")
)

var aro = []uint32{
0x4D34D34D, 0xD34D34D3, 0x34D34D34, 0x4D34D34D,
0xD34D34D3, 0x34D34D34, 0x4D34D34D, 0xD34D34D3,
}

type rabbitCipher struct {
xbit [8]uint32
cbit [8]uint32
Expand All @@ -32,10 +26,10 @@ type rabbitCipher struct {
// must be either zero len or 8 byte len, error will be returned on wrong key/iv len
func NewCipher(key []byte, iv []byte) (cipher.Stream, error) {
if len(key) != 16 {
return nil, invalidKeyLenErr
return nil, errInvalidKeyLen
}
if len(iv) != 0 && len(iv) != 8 {
return nil, invalidIVXLenErr
return nil, errInvalidIVXLen
}

c := new(rabbitCipher)
Expand All @@ -56,11 +50,12 @@ func (r *rabbitCipher) XORKeyStream(dst, src []byte) {
if alias.InexactOverlap(dst[:len(src)], src) {
panic("cryptobin/rabbit: invalid buffer overlap")
}

for i := range src {
if len(r.ks) == 0 {
r.extract()
}

dst[i] = src[i] ^ r.ks[0]
r.ks = r.ks[1:]
}
Expand All @@ -69,15 +64,15 @@ func (r *rabbitCipher) XORKeyStream(dst, src []byte) {
func (r *rabbitCipher) expandKey(key, iv []byte) {
var k [4]uint32
for i := range k {
k[i] = binary.LittleEndian.Uint32(key[i*4:])
k[i] = getu32(key[i*4:])
}

r.setupKey(k[:])

if len(iv) != 0 {
var v [4]uint16
for i := range v {
v[i] = binary.LittleEndian.Uint16(iv[i*2:])
v[i] = getu16(iv[i*2:])
}

r.setupIV(v[:])
Expand All @@ -93,17 +88,19 @@ func (r *rabbitCipher) setupKey(key []uint32) {
r.xbit[5] = key[1]<<16 | key[0]>>16
r.xbit[6] = key[3]
r.xbit[7] = key[2]<<16 | key[1]>>16
r.cbit[0] = bits.RotateLeft32(key[2], 16)
r.cbit[0] = rol32(key[2], 16)
r.cbit[1] = key[0]&0xffff0000 | key[1]&0xffff
r.cbit[2] = bits.RotateLeft32(key[3], 16)
r.cbit[2] = rol32(key[3], 16)
r.cbit[3] = key[1]&0xffff0000 | key[2]&0xffff
r.cbit[4] = bits.RotateLeft32(key[0], 16)
r.cbit[4] = rol32(key[0], 16)
r.cbit[5] = key[2]&0xffff0000 | key[3]&0xffff
r.cbit[6] = bits.RotateLeft32(key[1], 16)
r.cbit[6] = rol32(key[1], 16)
r.cbit[7] = key[3]&0xffff0000 | key[0]&0xffff

for i := 0; i < 4; i++ {
r.nextState()
}

r.cbit[0] ^= r.xbit[4]
r.cbit[1] ^= r.xbit[5]
r.cbit[2] ^= r.xbit[6]
Expand All @@ -123,6 +120,7 @@ func (r *rabbitCipher) setupIV(iv []uint16) {
r.cbit[5] ^= uint32(iv[3])<<16 | uint32(iv[1])
r.cbit[6] ^= uint32(iv[3])<<16 | uint32(iv[2])
r.cbit[7] ^= uint32(iv[2])<<16 | uint32(iv[0])

for i := 0; i < 4; i++ {
r.nextState()
}
Expand All @@ -133,17 +131,19 @@ func (r *rabbitCipher) nextState() {
for i := range r.cbit {
r.carry, r.cbit[i] = bits.Sub32(aro[i], r.cbit[i], r.carry)
}

for i := range GRX {
GRX[i] = gfunction(r.xbit[i], r.cbit[i])
}
r.xbit[0x00] = GRX[0] + bits.RotateLeft32(GRX[7], 16) + bits.RotateLeft32(GRX[6], 16)
r.xbit[0x01] = GRX[1] + bits.RotateLeft32(GRX[0], 8) + GRX[7]
r.xbit[0x02] = GRX[2] + bits.RotateLeft32(GRX[1], 16) + bits.RotateLeft32(GRX[0], 16)
r.xbit[0x03] = GRX[3] + bits.RotateLeft32(GRX[2], 8) + GRX[1]
r.xbit[0x04] = GRX[4] + bits.RotateLeft32(GRX[3], 16) + bits.RotateLeft32(GRX[2], 16)
r.xbit[0x05] = GRX[5] + bits.RotateLeft32(GRX[4], 8) + GRX[3]
r.xbit[0x06] = GRX[6] + bits.RotateLeft32(GRX[5], 16) + bits.RotateLeft32(GRX[4], 16)
r.xbit[0x07] = GRX[7] + bits.RotateLeft32(GRX[6], 8) + GRX[5]

r.xbit[0x00] = GRX[0] + rol32(GRX[7], 16) + rol32(GRX[6], 16)
r.xbit[0x01] = GRX[1] + rol32(GRX[0], 8) + GRX[7]
r.xbit[0x02] = GRX[2] + rol32(GRX[1], 16) + rol32(GRX[0], 16)
r.xbit[0x03] = GRX[3] + rol32(GRX[2], 8) + GRX[1]
r.xbit[0x04] = GRX[4] + rol32(GRX[3], 16) + rol32(GRX[2], 16)
r.xbit[0x05] = GRX[5] + rol32(GRX[4], 8) + GRX[3]
r.xbit[0x06] = GRX[6] + rol32(GRX[5], 16) + rol32(GRX[4], 16)
r.xbit[0x07] = GRX[7] + rol32(GRX[6], 8) + GRX[5]
}

func (r *rabbitCipher) extract() {
Expand All @@ -156,14 +156,8 @@ func (r *rabbitCipher) extract() {
sw[3] = r.xbit[6] ^ (r.xbit[3]>>16 | r.xbit[1]<<16)

for i := range sw {
binary.LittleEndian.PutUint32(r.sbit[i*4:], sw[i])
putu32(r.sbit[i*4:], sw[i])
}

r.ks = r.sbit[:]
}

func gfunction(u, v uint32) uint32 {
uv := uint64(u + v)
uv *= uv
return uint32(uv>>32) ^ uint32(uv)
}
67 changes: 65 additions & 2 deletions pkg/lakego-pkg/go-cryptobin/cipher/rabbitio/rabbit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package rabbitio_test

import (
"fmt"
"bytes"
"testing"
"encoding/hex"

"github.com/deatil/go-cryptobin/cipher/rabbitio"
)

func TestNewCipher(t *testing.T) {
func Test_NewCipher(t *testing.T) {
key, ivt := []byte("12345678abcdefgh"), []byte("1234qwer")
txt := "test NewReadercipher text dummy tx"
cph, err := rabbitio.NewCipher(key, ivt)
Expand All @@ -30,7 +32,68 @@ func TestNewCipher(t *testing.T) {

}

func BenchmarkNewCipher(b *testing.B) {
var testDatas = []struct {
key string
iv string
plain string
cipher string
} {
{
"12345678901234561234567890123456",
"",
"0000000000000000",
"d55293bba40cadf0",
},
{
"12345678901234561234567890123456",
"1234567812345678",
"0000000000000000",
"da7671fb2e61c40a",
},
{
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"1234567812345678",
"0000000000000000",
"22e8c9583f950d46",
},
}

func Test_Check(t *testing.T) {
for _, v := range testDatas {
keyBytes, _ := hex.DecodeString(v.key)
ivBytes, _ := hex.DecodeString(v.iv)
plainBytes, _ := hex.DecodeString(v.plain)
cipherBytes, _ := hex.DecodeString(v.cipher)

c, err := rabbitio.NewCipher(keyBytes, ivBytes)
if err != nil {
t.Fatal(err.Error())
}

var encrypted []byte = make([]byte, len(plainBytes))
c.XORKeyStream(encrypted[:], plainBytes)

if !bytes.Equal(encrypted, cipherBytes) {
t.Errorf("encryption/decryption failed: got %x, want %x", encrypted, cipherBytes)
}

// =================

c2, err := rabbitio.NewCipher(keyBytes, ivBytes)
if err != nil {
t.Fatal(err.Error())
}

var decrypted []byte = make([]byte, len(cipherBytes))
c2.XORKeyStream(decrypted[:], cipherBytes)

if !bytes.Equal(decrypted, plainBytes) {
t.Errorf("encryption/decryption failed: got %x, want %x", decrypted, plainBytes)
}
}
}

func Benchmark_NewCipher(b *testing.B) {
b.Run(fmt.Sprintf("bench %v", b.N), func(b *testing.B) {
for i := 0; i < b.N; i++ {
key, ivt := []byte("12345678abcdefgh"), []byte("1234qwer")
Expand Down
6 changes: 6 additions & 0 deletions pkg/lakego-pkg/go-cryptobin/cipher/rabbitio/sbox.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package rabbitio

var aro = []uint32{
0x4D34D34D, 0xD34D34D3, 0x34D34D34, 0x4D34D34D,
0xD34D34D3, 0x34D34D34, 0x4D34D34D, 0xD34D34D3,
}
Loading

0 comments on commit 75091df

Please sign in to comment.