package main import ( "bytes" "crypto/sha512" "encoding/base64" "encoding/binary" "dim13.org/signify/bhash" "golang.org/x/crypto/ed25519" ) var ( PKAlg = [2]byte{'E', 'd'} KDFAlg = [2]byte{'B', 'K'} ) type Sig struct { PKAlg [2]byte KeyNum [8]byte Sig [ed25519.SignatureSize]byte } type PubKey struct { PKAlg [2]byte KeyNum [8]byte PubKey [ed25519.PublicKeySize]byte } type EncKey struct { PKAlg [2]byte KDFAlg [2]byte KDFRounds uint32 Salt [16]byte Checksum [8]byte KeyNum [8]byte SecKey [ed25519.PrivateKeySize]byte } func (v *EncKey) XOR(key []byte) { if len(key) != len(v.SecKey) { panic("invalid key len") } for i := range key { v.SecKey[i] ^= key[i] } } func (v *EncKey) IsValid(pass []byte) bool { if v.KDFRounds > 0 { key := bhash.Pbkdf(pass, v.Salt[:], int(v.KDFRounds), len(v.SecKey)) v.XOR(key) } sum := sha512.Sum512(v.SecKey[:]) return bytes.Equal(sum[:len(v.Checksum)], v.Checksum[:]) } func Unmarshal(b []byte, v interface{}) error { buf := bytes.NewReader(b) dec := base64.NewDecoder(base64.StdEncoding, buf) if err := binary.Read(dec, binary.BigEndian, v); err != nil { return err } return nil } func Marshal(v interface{}) ([]byte, error) { buf := new(bytes.Buffer) enc := base64.NewEncoder(base64.StdEncoding, buf) if err := binary.Write(enc, binary.BigEndian, v); err != nil { return nil, err } if err := enc.Close(); err != nil { return nil, err } return buf.Bytes(), nil }