init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
package fpe
import (
"crypto/cipher"
"errors"
"math"
"math/big"
"xdx.jelly/xgcl/internal/xor"
)
func rev[T any](X []T) {
l := len(X) / 2
for i := 0; i < l; i++ {
t := X[i]
X[i] = X[l-i-1]
X[l-i-1] = t
}
}
// in = in0||in1||in2...
// out0 = Enc(iv ^ in0)
// out1 = Enc(out0 ^ in1)
// ...
// if iv == nil <==> iv = 0^16.
func prf(res []byte, b cipher.Block, iv []byte, in []byte) []byte {
xor.XorBytes(res, iv, in[:16])
b.Encrypt(res, res)
in = in[16:]
for len(in) > 0 {
xor.XorBytes(res, res, in[:16])
b.Encrypt(res, res)
in = in[16:]
}
return res
}
type FF1 struct {
cipher.Block
Alphabet
}
func NewFF1(b cipher.Block, a Alphabet) FPE {
return &FF1{
Block: b,
Alphabet: a,
}
}
func (f *FF1) round(P []byte, Q []byte, S []byte, A []Numeral, B []Numeral, i int, b int, d int, module *big.Int, isenc bool) {
Q[len(Q)-b-1] = byte(i)
f.Num(B).FillBytes(Q[len(Q)-b:])
prf(S, f.Block, P, Q)
for j := 1; j < (d+15)/16; j++ {
Sj := S[16*j : 16*j+16]
S[16*j+12] = byte(j >> 24)
S[16*j+13] = byte(j >> 16)
S[16*j+14] = byte(j >> 8)
S[16*j+15] = byte(j)
xor.XorBytes(Sj, S[:16], Sj)
f.Block.Encrypt(Sj, Sj)
}
y := new(big.Int).SetBytes(S[:d])
c := f.Num(A)
if isenc {
c.Add(c, y).Mod(c, module)
} else {
c.Sub(c, y).Mod(c, module)
}
f.Str(A, c)
}
func (f *FF1) endecrypt(T []byte, X []Numeral, isEnc bool) ([]Numeral, error) {
n := len(X)
if n <= 2 {
return nil, errors.New("input numeral string X must at least 2 characters")
}
radix := f.Alphabet.Radix()
t := len(T)
u := n / 2
v := n - u
b := (int(math.Ceil(float64(v)*math.Log2(float64(radix)))) + 7) >> 3
d := (b + 7) & (^3)
P := []byte{
1, 2, 1,
0, byte(radix >> 8), byte(radix),
10, byte(u),
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
}
f.Block.Encrypt(P, P)
// make a copy of X
res := make([]Numeral, len(X))
copy(res, X)
A := res[:u]
B := res[u:]
// Q := append(make([]byte, 0, (b+t+1+15)&(^15)), T...)
Q := make([]byte, (b+t+1+15)&(^15))
copy(Q, T)
S := make([]byte, (d+15)&(^15))
var moduleA, moduleB *big.Int
radixBig := big.NewInt(int64(radix))
// 如果输入X很大,这里的module会很大。
moduleA = new(big.Int).Exp(radixBig, big.NewInt(int64(u)), nil)
moduleB = moduleA
if v > u {
moduleB = radixBig.Mul(moduleB, radixBig)
}
if isEnc {
for i := 0; i < 10; i += 2 {
f.round(P, Q, S, A, B, i, b, d, moduleA, true)
f.round(P, Q, S, B, A, i+1, b, d, moduleB, true)
}
} else {
for i := 9; i >= 0; i -= 2 {
f.round(P, Q, S, B, A, i, b, d, moduleB, false)
f.round(P, Q, S, A, B, i-1, b, d, moduleA, false)
}
}
return res, nil
}
func (f *FF1) Encrypt(T []byte, X []Numeral) ([]Numeral, error) {
return f.endecrypt(T, X, true)
}
func (f FF1) Decrypt(T []byte, X []Numeral) ([]Numeral, error) {
return f.endecrypt(T, X, false)
}