1package main
2
3import (
4	"bufio"
5	"bytes"
6	"crypto/sha256"
7	"encoding/hex"
8	"fmt"
9	"golang.org/x/crypto/hkdf"
10	"io"
11	"os"
12	"strconv"
13	"strings"
14)
15
16func unhexlify(s string) []byte {
17	bytes, err := hex.DecodeString(s)
18	if err != nil {
19		panic(err)
20	}
21	return bytes
22}
23
24func verifier(l uint64, ikm, okm []byte) bool {
25	hash := sha256.New
26	hkdf := hkdf.New(hash, ikm, nil, nil)
27	okmComputed := make([]byte, l)
28	io.ReadFull(hkdf, okmComputed)
29	return bytes.Equal(okmComputed, okm)
30}
31
32func validateVectors(filename string) bool {
33	vectors, err := os.Open(filename)
34	if err != nil {
35		panic(err)
36	}
37	defer vectors.Close()
38
39	var segments []string
40	var l uint64
41	var ikm, okm string
42
43	scanner := bufio.NewScanner(vectors)
44	for scanner.Scan() {
45		segments = strings.Split(scanner.Text(), " = ")
46
47		switch {
48		case strings.ToUpper(segments[0]) == "L":
49			l, err = strconv.ParseUint(segments[1], 10, 64)
50			if err != nil {
51				panic(err)
52			}
53		case strings.ToUpper(segments[0]) == "IKM":
54			ikm = segments[1]
55		case strings.ToUpper(segments[0]) == "OKM":
56			okm = segments[1]
57		}
58	}
59	return verifier(l, unhexlify(ikm), unhexlify(okm))
60}
61
62func main() {
63	if validateVectors("vectors/cryptography_vectors/KDF/hkdf-generated.txt") {
64		fmt.Println("HKDF OK.")
65	} else {
66		fmt.Println("HKDF failed.")
67		os.Exit(1)
68	}
69}
70