aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/development/custom-vectors/hkdf.rst28
-rw-r--r--docs/development/custom-vectors/hkdf/generate_hkdf.py39
-rw-r--r--docs/development/custom-vectors/hkdf/verify_hkdf.go69
-rw-r--r--docs/development/test-vectors.rst6
-rw-r--r--vectors/cryptography_vectors/KDF/hkdf-generated.txt9
5 files changed, 149 insertions, 2 deletions
diff --git a/docs/development/custom-vectors/hkdf.rst b/docs/development/custom-vectors/hkdf.rst
new file mode 100644
index 00000000..0e1a729a
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf.rst
@@ -0,0 +1,28 @@
+HKDF vector creation
+====================
+
+This page documents the code that was used to generate a longer
+HKDF test vector (1200 bytes) than is available in RFC 5869. All
+the vectors were generated using OpenSSL and verified with Go.
+
+Creation
+--------
+
+The following Python script was run to generate the vector files.
+
+.. literalinclude:: /development/custom-vectors/hkdf/generate_hkdf.py
+
+Download link: :download:`generate_hkdf.py
+</development/custom-vectors/hkdf/generate_hkdf.py>`
+
+
+Verification
+------------
+
+The following Go code was used to verify the vectors.
+
+.. literalinclude:: /development/custom-vectors/hkdf/verify_hkdf.go
+ :language: go
+
+Download link: :download:`verify_hkdf.go
+</development/custom-vectors/hkdf/verify_hkdf.go>`
diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py
new file mode 100644
index 00000000..767aedd8
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py
@@ -0,0 +1,39 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+IKM = binascii.unhexlify(b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
+L = 1200
+OKM = HKDF(
+ algorithm=hashes.SHA256(), length=L, salt=None, info=None,
+ backend=default_backend()
+).derive(IKM)
+
+
+def _build_vectors():
+ output = []
+ output.append("COUNT = 0")
+ output.append("Hash = SHA-256")
+ output.append("IKM = " + binascii.hexlify(IKM).decode("ascii"))
+ output.append("salt = ")
+ output.append("info = ")
+ output.append("L = {}".format(L))
+ output.append("OKM = " + binascii.hexlify(OKM).decode("ascii"))
+ return "\n".join(output)
+
+
+def _write_file(data, filename):
+ with open(filename, 'w') as f:
+ f.write(data)
+
+
+if __name__ == '__main__':
+ _write_file(_build_vectors(), 'hkdf.txt')
diff --git a/docs/development/custom-vectors/hkdf/verify_hkdf.go b/docs/development/custom-vectors/hkdf/verify_hkdf.go
new file mode 100644
index 00000000..ddeb3d8e
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/verify_hkdf.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/sha256"
+ "encoding/hex"
+ "fmt"
+ "golang.org/x/crypto/hkdf"
+ "io"
+ "os"
+ "strconv"
+ "strings"
+)
+
+func unhexlify(s string) []byte {
+ bytes, err := hex.DecodeString(s)
+ if err != nil {
+ panic(err)
+ }
+ return bytes
+}
+
+func verifier(l uint64, ikm, okm []byte) bool {
+ hash := sha256.New
+ hkdf := hkdf.New(hash, ikm, nil, nil)
+ okmComputed := make([]byte, l)
+ io.ReadFull(hkdf, okmComputed)
+ return bytes.Equal(okmComputed, okm)
+}
+
+func validateVectors(filename string) bool {
+ vectors, err := os.Open(filename)
+ if err != nil {
+ panic(err)
+ }
+ defer vectors.Close()
+
+ var segments []string
+ var l uint64
+ var ikm, okm string
+
+ scanner := bufio.NewScanner(vectors)
+ for scanner.Scan() {
+ segments = strings.Split(scanner.Text(), " = ")
+
+ switch {
+ case strings.ToUpper(segments[0]) == "L":
+ l, err = strconv.ParseUint(segments[1], 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ case strings.ToUpper(segments[0]) == "IKM":
+ ikm = segments[1]
+ case strings.ToUpper(segments[0]) == "OKM":
+ okm = segments[1]
+ }
+ }
+ return verifier(l, unhexlify(ikm), unhexlify(okm))
+}
+
+func main() {
+ if validateVectors("vectors/cryptography_vectors/KDF/hkdf-generated.txt") {
+ fmt.Println("HKDF OK.")
+ } else {
+ fmt.Println("HKDF failed.")
+ os.Exit(1)
+ }
+}
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index 6cee4fe8..817bdaf6 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -476,8 +476,8 @@ Creating test vectors
When official vectors are unavailable ``cryptography`` may choose to build
its own using existing vectors as source material.
-Custom Symmetric Vectors
-~~~~~~~~~~~~~~~~~~~~~~~~
+Created Vectors
+~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 1
@@ -486,6 +486,8 @@ Custom Symmetric Vectors
custom-vectors/cast5
custom-vectors/idea
custom-vectors/seed
+ custom-vectors/hkdf
+
If official test vectors appear in the future the custom generated vectors
should be discarded.
diff --git a/vectors/cryptography_vectors/KDF/hkdf-generated.txt b/vectors/cryptography_vectors/KDF/hkdf-generated.txt
new file mode 100644
index 00000000..76b28f52
--- /dev/null
+++ b/vectors/cryptography_vectors/KDF/hkdf-generated.txt
@@ -0,0 +1,9 @@
+# A 1200 byte HKDF vector built for https://github.com/pyca/cryptography
+# Created with OpenSSL and verified against a Go implementation
+COUNT = 0
+Hash = SHA-256
+IKM = 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
+salt =
+info =
+L = 1200
+OKM = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8b2fb61057244b36c6ddd287f634795e7d80d5fe26bfc36def6dc129c29271a0eb7ab14bd2ca88259f8a3a92ac2ec0e3e4fa046a4b90b137ce44a2105152c2db1480a0ac2e999db47e000833856093a641da082a94429eccf5143b1780234baacfa9d89b850473f2c678f7caa96b00efdace2d71fd42412465308f2374960b6c3c35d3eaaea0b8f7e595fa9cc5db25a91bc0120bad6223b25e378f514686eedfc9f102e045868e64ab02f1c021868b4e6686e295a10a94524e8730d79b4d3f890c387763a19a248577e9aad8e23ba2bacfc9230fb144a7730d3ceaf799d1de1032951dc1fddea17f96981fbf6b05e4878df782b497f60c3eb4cff0c249d8c1bbeabca6e66c71cc79314f2bfc758dd41c9872cbb461e17cff0002a9fdee546953f98dde7d4aa828a68f4ccd950d371d1eb3839219bfdb9ef911d3602d78bd2f6a970a6c437763c81821e131325fa77fc8963a021b87caa8e35ad2a37f2237a2143c1966817e4da9912a2013cd7239c5fad2e4599f9ce20bcd8cd0ff1516f9f2496ecce94ccd82cde5c9ef120bbaf640d6292d6916d40d99d9d4657dd2fdf2d4e5a5bbb27446ed58a3d637d0811c555273b0fd3699161acb58205fe6cfd45245249a7ecfc4c3d0668de270e6962d1d19fffa4b8df099cd4022cb0df18ffcffff5b046f0fc082ed16f99b416b7bbd4982ad0afc8b1dc332a8058729065538dbe9422b795a887af9c5d50ee85a60871be14c7f2d1111f197378d99065fb89a0f57b7342792798963f00910e5fad47a64477f41c07ac6058e01932502eb6faa88a6cc21e115b8e3ddfae8fdcaab60d13d808f3206b4e9da8bd4ae1108b2a01d256a02c9131ea0f6203c8c6e55ec7ae16bb19cf3239490085713679e7c304ce254e2897c0fd3bc97263a562fe161dcf6d21e841eb2266aa1cfaaaf6fc094111ad4b2e4d8e05b50854ae5de83d81842c689a55b1be7d575ac50e81d7708c262c1f70452884c7714abef03b88b85a41e895a0e7529b8d631e5e77583175c80e86e45802763eaba0471d11fc885b34fa4b5309a9fe49a5215d4aa21041c53a30a1e97250f6445ce537bb3efb1fa17f141db69c7d97ab48cb34c33bef0ded5d4c320fe554a0faea353a5579cb08f072565bbd49d167186f39a298a553f320bb89eaee54151b08deef49b7b630af62b4d7be1f4965a53c67e7d3e34a6d8263ee86f44dfbe019cbe8e3bd4ed0cda06985127ff8d1794e6321891a950f329aca2b36b16f8a2bb910b1206a5c238ef079df12ecb0f0f7e3e4f8a64bfd23b57e9d286a1c8d2e9290d9a4f1d20ec100aac7dc90783cb2ecfd69d71a91dcc3913494ebf7a7a00d1051102d7f268e761855b985c2599350f15ee0d4093244113185bc7031d2431ccd9391fcd58a85e068458b644ed265b3f103852a2d7bbf0d2c1d7c02e30ff1ec552f09bc60e36393391cec05926009520af12d96387cc55b9553e79da8b2eb9303ecf15bb289530c3d65c4cc5a68f8ece60a37522fe3d0e6ba4ddfb560a45717456cf91c5dc5b8117da68bc49968ec1e35852bbc54e554fb839b35f6c3b5c09530855d8691fc0f126f67346f949bd813a6db44c513d1e61b8c8789eb9e823d1a38862dca1c5331da