github.com/theQRL/go-zond@v0.1.1/pqcrypto/crypto.go (about) 1 package pqcrypto 2 3 import ( 4 "bufio" 5 "encoding/hex" 6 "errors" 7 "fmt" 8 "io" 9 "os" 10 11 qrllibCommon "github.com/theQRL/go-qrllib/common" 12 "github.com/theQRL/go-qrllib/dilithium" 13 "github.com/theQRL/go-zond/common" 14 ) 15 16 const DilithiumSignatureLength = dilithium.CryptoBytes 17 18 const DilithiumPublicKeyLength = dilithium.CryptoPublicKeyBytes 19 20 // DigestLength sets the signature digest exact length 21 const DigestLength = 32 22 23 // LoadDilithium loads Dilithium from the given file having hex seed (not extended hex seed). 24 func LoadDilithium(file string) (*dilithium.Dilithium, error) { 25 fd, err := os.Open(file) 26 if err != nil { 27 return nil, err 28 } 29 defer fd.Close() 30 31 r := bufio.NewReader(fd) 32 buf := make([]byte, qrllibCommon.SeedSize*2) 33 n, err := readASCII(buf, r) 34 if err != nil { 35 return nil, err 36 } else if n != len(buf) { 37 return nil, fmt.Errorf("key file too short, want %v hex characters", qrllibCommon.SeedSize*2) 38 } 39 if err := checkKeyFileEnd(r); err != nil { 40 return nil, err 41 } 42 43 return HexToDilithium(string(buf)) 44 } 45 46 func GenerateDilithiumKey() (*dilithium.Dilithium, error) { 47 return dilithium.New() 48 } 49 50 // readASCII reads into 'buf', stopping when the buffer is full or 51 // when a non-printable control character is encountered. 52 func readASCII(buf []byte, r *bufio.Reader) (n int, err error) { 53 for ; n < len(buf); n++ { 54 buf[n], err = r.ReadByte() 55 switch { 56 case err == io.EOF || buf[n] < '!': 57 return n, nil 58 case err != nil: 59 return n, err 60 } 61 } 62 return n, nil 63 } 64 65 // checkKeyFileEnd skips over additional newlines at the end of a key file. 66 func checkKeyFileEnd(r *bufio.Reader) error { 67 for i := 0; ; i++ { 68 b, err := r.ReadByte() 69 switch { 70 case err == io.EOF: 71 return nil 72 case err != nil: 73 return err 74 case b != '\n' && b != '\r': 75 return fmt.Errorf("invalid character %q at end of key file", b) 76 case i >= 2: 77 return errors.New("key file too long, want 64 hex characters") 78 } 79 } 80 } 81 82 // ToDilithiumUnsafe blindly converts a binary blob to a private key. It should almost 83 // never be used unless you are sure the input is valid and want to avoid hitting 84 // errors due to bad origin encoding (0 prefixes cut off). 85 func ToDilithiumUnsafe(seed []byte) *dilithium.Dilithium { 86 var sizedSeed [qrllibCommon.SeedSize]uint8 87 copy(sizedSeed[:], seed) 88 d, err := dilithium.NewDilithiumFromSeed(sizedSeed) 89 if err != nil { 90 return nil 91 } 92 return d 93 } 94 95 // HexToDilithium parses a hex seed (not extended hex seed). 96 func HexToDilithium(hexSeedStr string) (*dilithium.Dilithium, error) { 97 b, err := hex.DecodeString(hexSeedStr) 98 if byteErr, ok := err.(hex.InvalidByteError); ok { 99 return nil, fmt.Errorf("invalid hex character %q in private key", byte(byteErr)) 100 } else if err != nil { 101 return nil, errors.New("invalid hex data for private key") 102 } 103 104 var hexSeed [qrllibCommon.SeedSize]uint8 105 copy(hexSeed[:], b) 106 107 return dilithium.NewDilithiumFromSeed(hexSeed) 108 } 109 110 func DilithiumPKToAddress(publicKey []byte) common.Address { 111 var pk [DilithiumPublicKeyLength]uint8 112 copy(pk[:], publicKey) 113 return dilithium.GetDilithiumAddressFromPK(pk) 114 } 115 116 func zeroBytes(d **dilithium.Dilithium) { 117 *d = nil 118 }