Files
2026-05-27 23:03:00 +08:00

183 lines
4.3 KiB
Go

package fpe
import (
"fmt"
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/assert"
"xdx.jelly/xgcl/grand"
"xdx.jelly/xgcl/sm/sm4"
)
func TestNum(t *testing.T) {
N := 1000
A := make([]Numeral, N)
B := make([]Numeral, N)
for r := 2; r < 100; r++ {
radix := NewRadix(r)
for i := 1; i <= N; i++ {
for j := 0; j < i; j++ {
A[j] = Numeral(rand.Int31() % int32(r))
}
numSwitch = false
a0 := radix.Num(A[:i])
numSwitch = true
a1 := radix.Num(A[:i])
assert.Equal(t, a0.Cmp(a1), 0)
radix.Str(B[:i], a0)
assert.Equal(t, A[:i], B[:i])
}
}
}
func TestStr(t *testing.T) {
f := Alpha
// 24948832942366750129003083595837476696096111951836798179448429117431251233398075403977925597490
A := []Numeral{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
}
for i := 20; i <= len(A); i++ {
a := f.Num(A[:i])
B := make([]Numeral, i)
f.Str(B, a)
for j := range B {
if B[j] != A[j] {
t.Fatal()
}
}
}
}
// BenchmarkAlphabet-10 1158810 1020 ns/op 88 B/op 3 allocs/op
// BenchmarkAlphabet-10 3776529 310.4 ns/op 96 B/op 4 allocs/op
func BenchmarkNum(b *testing.B) {
f := Alpha
A := []Numeral{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
f.Num(A)
}
}
// BenchmarkStr-10 556981 2130 ns/op 104 B/op 2 allocs/op
// BenchmarkStr-10 3134851 382.2 ns/op 104 B/op 2 allocs/op
func BenchmarkStr(b *testing.B) {
f := Alpha
A := []Numeral{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
}
a := f.Num(A)
B := make([]Numeral, len(A))
b.ResetTimer()
for i := 0; i < b.N; i++ {
f.Str(B, a)
}
}
func TestFF1(t *testing.T) {
// fmt.Printf("%x\n", ^uint64(15))
// 密钥
key := grand.GetRandom(16)
// 使用SM4加密算法
b, _ := sm4.NewCipher(key)
// tweak
T := grand.GetRandom(16)
// interface FPE
f := NewFF1(b, NewAlphabet("abcdefghijklmnopqrstuvwxyz "))
plainString0 := "hello world"
plain0, err := f.Encode(plainString0)
assert.Nil(t, err)
cipher, err := f.Encrypt(T, plain0)
assert.Nil(t, err)
cipherString, err := f.Decode(cipher)
assert.Nil(t, err)
fmt.Println("Cipher string:", cipherString)
plain1, err := f.Decrypt(T, cipher)
assert.Nil(t, err)
assert.Equal(t, plain0, plain1)
plainString1, err := f.Decode(plain1)
assert.Nil(t, err)
fmt.Println("Decrypt string:", plainString1)
assert.Equal(t, plainString0, plainString1)
}
// BenchmarkFF1-10 129781 8683 ns/op 4256 B/op 154 allocs/op
// BenchmarkFF1-10 325104 3694 ns/op 2808 B/op 99 allocs/op
func BenchmarkFF1(b *testing.B) {
key := grand.GetRandom(16)
block, _ := sm4.NewCipher(key)
T := grand.GetRandom(16)
f := NewFF1(block, Printable)
plainString0 := "hello world"
plain0, _ := f.Encode(plainString0)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = f.Encrypt(T, plain0)
}
}
// // 密文长度 加密速率(MBps)
// // 32 2.55
// // 64 3.99
// // 128 3.58
// // 256 3.82
// // 512 3.65
// // 1024 3.15
// // 2048 2.38
// // 4096 1.58
// // 8192 0.94
func TestSpeed(t *testing.T) {
key := grand.GetRandom(16)
block, _ := sm4.NewCipher(key)
T := grand.GetRandom(16)
f := NewFF1(block, Printable)
fmt.Println("密文长度 加密速率(MBps)")
for plainLen, cnt := 32, 10000; plainLen < 10000; plainLen, cnt = plainLen*2, cnt/2 {
b := make([]byte, plainLen)
for i := range b {
b[i] = byte(rand.Uint32()%26 + 'a')
}
plain := string(b)
start := time.Now()
for i := 0; i < cnt; i++ {
n, _ := f.Encode(plain)
_, _ = f.Encrypt(T, n)
}
end := time.Now()
elapsed := end.Sub(start)
fmt.Printf("%4d %.2f\n", plainLen, float64(len(plain)*cnt)/(1024*1024*elapsed.Seconds()))
}
}