inistal commit
This commit is contained in:
commit
023bb97155
7 changed files with 661 additions and 0 deletions
196
xifrat.go
Normal file
196
xifrat.go
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
package goxifrat
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/subtle"
|
||||
"strconv"
|
||||
//"crypto/sha512"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
const (
|
||||
P = 16
|
||||
N = 64
|
||||
R = 64
|
||||
)
|
||||
|
||||
var st = [P][P]uint8{
|
||||
{7, 9, 13, 10, 15, 2, 0, 6, 3, 12, 8, 4, 1, 5, 14, 11},
|
||||
{1, 15, 6, 3, 9, 4, 11, 13, 10, 5, 14, 2, 7, 12, 8, 0},
|
||||
{3, 0, 12, 1, 11, 8, 9, 5, 7, 13, 2, 14, 10, 6, 4, 15},
|
||||
{4, 6, 15, 8, 13, 1, 5, 9, 14, 11, 10, 7, 2, 0, 3, 12},
|
||||
{0, 3, 8, 15, 10, 12, 7, 14, 9, 2, 13, 5, 11, 4, 6, 1},
|
||||
{10, 11, 5, 7, 0, 14, 15, 12, 1, 6, 4, 8, 3, 13, 2, 9},
|
||||
{5, 14, 10, 13, 8, 11, 4, 3, 6, 1, 15, 0, 12, 7, 9, 2},
|
||||
{15, 1, 4, 0, 7, 6, 10, 2, 11, 14, 5, 13, 9, 8, 12, 3},
|
||||
{12, 8, 3, 6, 14, 0, 2, 10, 13, 7, 9, 11, 5, 1, 15, 4},
|
||||
{13, 2, 7, 5, 4, 9, 8, 1, 12, 3, 0, 15, 6, 10, 11, 14},
|
||||
{6, 4, 1, 12, 2, 15, 14, 7, 5, 10, 11, 9, 13, 3, 0, 8},
|
||||
{9, 7, 2, 11, 1, 13, 3, 4, 0, 8, 12, 6, 15, 14, 5, 10},
|
||||
{11, 10, 14, 9, 3, 5, 1, 8, 15, 4, 6, 12, 0, 2, 13, 7},
|
||||
{14, 5, 11, 2, 12, 10, 6, 0, 4, 15, 1, 3, 8, 9, 7, 13},
|
||||
{8, 12, 0, 4, 5, 3, 13, 11, 2, 9, 7, 10, 14, 15, 1, 6},
|
||||
{2, 13, 9, 14, 6, 7, 12, 15, 8, 0, 3, 1, 4, 11, 10, 5},
|
||||
}
|
||||
|
||||
func m(a, b [N]uint8) (r [N]uint8) {
|
||||
for j := 0; j < N; j++ {
|
||||
r[j] = st[a[j]][b[j]]
|
||||
}
|
||||
e := rn[0]
|
||||
for i := 0; i < R*N; i++ {
|
||||
d := rn[i+1]
|
||||
r[d] = st[r[d]][r[e]]
|
||||
e = d
|
||||
}
|
||||
for j := 0; j < N; j++ {
|
||||
r[j] = st[r[j]][b[j]]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type KeyAgreement struct {
|
||||
P [N]uint8
|
||||
C [N]uint8
|
||||
S1 [N]uint8
|
||||
S2 [N]uint8
|
||||
init bool
|
||||
}
|
||||
|
||||
func NewKeyAgreement(random io.Reader) (k *KeyAgreement, err error) {
|
||||
p, err := randomArray(random)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &KeyAgreement{P: p}, nil
|
||||
}
|
||||
|
||||
func (k *KeyAgreement) InitPhase(random io.Reader) (b []byte, err error) {
|
||||
k.C, err = randomArray(random)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
k.S1 = m(k.C, k.P)
|
||||
k.S2 = m(k.P, k.C)
|
||||
b = append(b, encode(k.C)...)
|
||||
b = append(b, encode(k.S1)...)
|
||||
k.init = true
|
||||
return
|
||||
}
|
||||
|
||||
func (k *KeyAgreement) SharedSecret(buf []byte) (sec, b []byte, err error) {
|
||||
if !k.init {
|
||||
if l := len(buf); l != 64 {
|
||||
return nil, nil, errors.New("xifrat: bad buffer length: " + strconv.Itoa(l))
|
||||
}
|
||||
k.C = decode(buf[:32])
|
||||
buf = buf[32:]
|
||||
k.S1 = m(k.C, k.P)
|
||||
k.S2 = m(k.P, k.C)
|
||||
k.init = true
|
||||
}
|
||||
if l := len(buf); l != KeySize {
|
||||
return nil, nil, errors.New("xifrat: bad buffer length: " + strconv.Itoa(l))
|
||||
}
|
||||
b = encode(k.S1)
|
||||
sec = encode(m(decode(buf), k.S2))
|
||||
return
|
||||
}
|
||||
|
||||
func encode(a [N]uint8) (buf []byte) {
|
||||
buf = make([]byte, len(a)/2)
|
||||
c := 0
|
||||
for i := 0; i < len(a); i++ {
|
||||
b := byte(a[i])
|
||||
i++
|
||||
buf[c] = (b << 4) | a[i]
|
||||
c++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
KeySize = 32
|
||||
SigSize = 96
|
||||
)
|
||||
|
||||
func decode(buf []byte) (a [N]uint8) {
|
||||
c := 0
|
||||
for _, b := range buf {
|
||||
a[c] = uint8(b >> 4)
|
||||
c++
|
||||
a[c] = uint8((b << 4) >> 4)
|
||||
c++
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
C [N]uint8
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
Q [N]uint8
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
|
||||
func (priv *PrivateKey) Sign(random io.Reader, digest []byte) (sig []byte, err error) {
|
||||
if l := len(digest); l != KeySize {
|
||||
return nil, errors.New("xifrat: bad digest length: " + strconv.Itoa(l))
|
||||
}
|
||||
k, err := randomArray(random)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
hash := decode(digest)
|
||||
s := m(hash, priv.Q)
|
||||
ck := m(priv.PublicKey.C, k)
|
||||
qk := m(priv.Q, k)
|
||||
sig = append(sig, encode(s)...)
|
||||
sig = append(sig, encode(ck)...)
|
||||
sig = append(sig, encode(qk)...)
|
||||
return
|
||||
}
|
||||
|
||||
func Verify(pub *PublicKey, digest, sig []byte) bool {
|
||||
if l := len(digest); l != KeySize {
|
||||
panic("xifrat: bad digest length: " + strconv.Itoa(l))
|
||||
}
|
||||
if l := len(sig); l != SigSize {
|
||||
panic("xifrat: bad signature length: " + strconv.Itoa(l))
|
||||
}
|
||||
s := decode(sig[:32])
|
||||
ck := decode(sig[32:64])
|
||||
qk := decode(sig[64:96])
|
||||
hash := decode(digest)
|
||||
v1 := m(s, ck)
|
||||
v2 := m(m(hash, pub.C), qk)
|
||||
return subtle.ConstantTimeCompare(encode(v1), encode(v2)) == 1
|
||||
}
|
||||
|
||||
func randomArray(random io.Reader) (a [N]uint8, err error) {
|
||||
buf := make([]byte, 32)
|
||||
_, err = random.Read(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
a = decode(buf)
|
||||
return
|
||||
}
|
||||
|
||||
func GenerateKey(random io.Reader) (p *PrivateKey, err error) {
|
||||
pub, err := randomArray(random)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv, err := randomArray(random)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PrivateKey{PublicKey{pub}, priv}, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue