Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add PQC support to the Proton branch #231

Draft
wants to merge 36 commits into
base: Proton
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
29bcd2a
Update GitHub workflow branches
twiss Jul 12, 2022
bd59a91
Add support for automatic forwarding (#54)
larabr Jul 12, 2022
783ef59
openpgp: Add support for symmetric subkeys (#74)
Mandragorian Jul 12, 2022
37452a3
Fix HMAC hash algorithm ID parsing and serializing
twiss Jul 13, 2022
febcea6
Rename branch to Proton
wussler Jan 17, 2023
c2b7cfe
Add full forwarding support
wussler Feb 24, 2023
197f38d
Use forwardee idenitity in forwarding key generation
wussler Mar 7, 2023
c7c4f36
Convert all valid subkeys when issuing a forwarding key
wussler Mar 20, 2023
34e4fe1
Resign keys and relax flag requirements
wussler Mar 21, 2023
d86ac43
Create a copy of the encrypted key when forwarding
wussler Mar 21, 2023
3a0e6ac
Use fingerprints instead of KeyIDs
wussler Mar 22, 2023
53b20e9
fix: Address rebase on version 2 issues
lubux Sep 15, 2023
5a964bd
feat: Add forwarding to v2 api
lubux Sep 15, 2023
a7a9cdc
fix: Address warnings
lubux Sep 15, 2023
972ccd8
feat: Add symmetric keys to v2
lubux Sep 15, 2023
66300b5
fix(v2): Do not allow encrpytion with a forwarding key
lubux Sep 26, 2023
8815d5b
fix(v2): Adapt NewForwardingEntity to refactored NewEntity
lubux Oct 5, 2023
e7d584c
Replace ioutil.ReadAll with io.ReadAll
lubux Jan 18, 2024
e68b818
Fix HMAC generation (#204)
wussler Mar 14, 2024
d537e95
Full PQC support (+12 squashed commits)
wussler Jul 19, 2022
11bb422
Adapt PQC to the v2 API
lubux Jul 19, 2024
bd63291
Remove sphincs PQC logic
lubux Jul 19, 2024
f8daf26
fix: Remove fmt.Println statements
lubux Sep 12, 2024
b68ddfb
chore: Run go fmt on openpgp folder
lubux Sep 12, 2024
bce1652
Remove PQC algorithms with brainpool and nist curves
lubux Sep 12, 2024
972f2c6
Update links to PQC draft-rfc
lubux Sep 12, 2024
28c613e
feat: Update to latest circle version
lubux Sep 12, 2024
820b6b5
feat: Derive ML-DSA keys from seed
lubux Sep 12, 2024
a993e70
ci: Remove testing on old go versions
lubux Sep 24, 2024
2e3a702
feat: Fallback to AES256 if all recipients are PQ
lubux Sep 24, 2024
8be8c23
refactor: Improve mlkem readability
lubux Sep 24, 2024
e9782f8
feat: Integrate review feedback
lubux Sep 27, 2024
bcbd610
feat: Update circl to v1.5.0
lubux Oct 11, 2024
d8b79f7
fix: Update curve448 integration test
lubux Oct 11, 2024
384a0e0
chore: Add kmac back
lubux Oct 11, 2024
86c81cb
feat: Update to new kmac key combiner in kem
lubux Oct 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 1 addition & 20 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
branches: [ main, Proton ]

jobs:

Expand All @@ -26,22 +26,3 @@ jobs:

- name: Randomized test suite 2
run: go test -v ./... -run RandomizeSlow -count=32

test-old:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go 1.17
uses: actions/setup-go@v3
with:
go-version: 1.17

- name: Short test
run: go test -short -v ./...

- name: Randomized test suite 1
run: go test -v ./... -run RandomizeFast -count=512

- name: Randomized test suite 2
run: go test -v ./... -run RandomizeSlow -count=32
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module github.com/ProtonMail/go-crypto

go 1.17
go 1.22.0

require (
github.com/cloudflare/circl v1.3.7
golang.org/x/crypto v0.17.0
github.com/cloudflare/circl v1.5.0
golang.org/x/crypto v0.25.0
)

require golang.org/x/sys v0.16.0 // indirect
require golang.org/x/sys v0.22.0 // indirect
50 changes: 6 additions & 44 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,44 +1,6 @@
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
145 changes: 145 additions & 0 deletions internal/kmac/kmac.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package kmac provides function for creating KMAC instances.
// KMAC is a Message Authentication Code that based on SHA-3 and
// specified in NIST Special Publication 800-185, "SHA-3 Derived Functions:
// cSHAKE, KMAC, TupleHash and ParallelHash" [1]
//
// [1] https://doi.org/10.6028/NIST.SP.800-185
package kmac

import (
"encoding/binary"
"hash"

"golang.org/x/crypto/sha3"
)

const (
// According to [1]:
// "When used as a MAC, applications of this Recommendation shall
// not select an output length L that is less than 32 bits, and
// shall only select an output length less than 64 bits after a
// careful risk analysis is performed."
// 64 bits was selected for safety.
kmacMinimumTagSize = 8
rate128 = 168
rate256 = 136
)

// KMAC specific context
type kmac struct {
sha3.ShakeHash // cSHAKE context and Read/Write operations
tagSize int // tag size
// initBlock is the KMAC specific initialization set of bytes. It is initialized
// by newKMAC function and stores the key, encoded by the method specified in 3.3 of [1].
// It is stored here in order for Reset() to be able to put context into
// initial state.
initBlock []byte
rate int
}

// NewKMAC128 returns a new KMAC hash providing 128 bits of security using
// the given key, which must have 16 bytes or more, generating the given tagSize
// bytes output and using the given customizationString.
// Note that unlike other hash implementations in the standard library,
// the returned Hash does not implement encoding.BinaryMarshaler
// or encoding.BinaryUnmarshaler.
func NewKMAC128(key []byte, tagSize int, customizationString []byte) hash.Hash {
if len(key) < 16 {
panic("Key must not be smaller than security strength")
}
c := sha3.NewCShake128([]byte("KMAC"), customizationString)
return newKMAC(key, tagSize, c, rate128)
}

// NewKMAC256 returns a new KMAC hash providing 256 bits of security using
// the given key, which must have 32 bytes or more, generating the given tagSize
// bytes output and using the given customizationString.
// Note that unlike other hash implementations in the standard library,
// the returned Hash does not implement encoding.BinaryMarshaler
// or encoding.BinaryUnmarshaler.

func NewKMAC256(key []byte, tagSize int, customizationString []byte) hash.Hash {
if len(key) < 32 {
panic("Key must not be smaller than security strength")
}
c := sha3.NewCShake256([]byte("KMAC"), customizationString)
return newKMAC(key, tagSize, c, rate256)
}

func newKMAC(key []byte, tagSize int, c sha3.ShakeHash, rate int) hash.Hash {
if tagSize < kmacMinimumTagSize {
panic("tagSize is too small")
}
k := &kmac{ShakeHash: c, tagSize: tagSize, rate: rate}
// leftEncode returns max 9 bytes
k.initBlock = make([]byte, 0, 9+len(key))
k.initBlock = append(k.initBlock, leftEncode(uint64(len(key)*8))...)
k.initBlock = append(k.initBlock, key...)
k.Write(bytepad(k.initBlock, k.BlockSize()))
return k
}

// Reset resets the hash to initial state.
func (k *kmac) Reset() {
k.ShakeHash.Reset()
k.Write(bytepad(k.initBlock, k.BlockSize()))
}

// BlockSize returns the hash block size.
func (k *kmac) BlockSize() int {
return k.rate
}

// Size returns the tag size.
func (k *kmac) Size() int {
return k.tagSize
}

// Sum appends the current KMAC to b and returns the resulting slice.
// It does not change the underlying hash state.
func (k *kmac) Sum(b []byte) []byte {
dup := k.ShakeHash.Clone()
dup.Write(rightEncode(uint64(k.tagSize * 8)))
hash := make([]byte, k.tagSize)
dup.Read(hash)
return append(b, hash...)
}

func bytepad(input []byte, w int) []byte {
// leftEncode always returns max 9 bytes
buf := make([]byte, 0, 9+len(input)+w)
buf = append(buf, leftEncode(uint64(w))...)
buf = append(buf, input...)
padlen := w - (len(buf) % w)
return append(buf, make([]byte, padlen)...)
}

func leftEncode(value uint64) []byte {
var b [9]byte
binary.BigEndian.PutUint64(b[1:], value)
// Trim all but last leading zero bytes
i := byte(1)
for i < 8 && b[i] == 0 {
i++
}
// Prepend number of encoded bytes
b[i-1] = 9 - i
return b[i-1:]
}

func rightEncode(value uint64) []byte {
var b [9]byte
binary.BigEndian.PutUint64(b[:8], value)
// Trim all but last leading zero bytes
i := byte(0)
for i < 7 && b[i] == 0 {
i++
}
// Append number of encoded bytes
b[8] = 8 - i
return b[i:]
}
133 changes: 133 additions & 0 deletions internal/kmac/kmac_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package kmac_test implements a vector-based test suite for the cSHAKE KMAC implementation
package kmac_test

import (
"bytes"
"encoding/hex"
"fmt"
"hash"
"testing"

"github.com/ProtonMail/go-crypto/internal/kmac"
)

// Test vectors from
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/cSHAKE_samples.pdf
var kmacTests = []struct {
security int
key, data, customization, tag string
}{
{
128,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"00010203",
"",
"E5780B0D3EA6F7D3A429C5706AA43A00FADBD7D49628839E3187243F456EE14E",
},
{
128,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"00010203",
"My Tagged Application",
"3B1FBA963CD8B0B59E8C1A6D71888B7143651AF8BA0A7070C0979E2811324AA5",
},
{
128,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7",
"My Tagged Application",
"1F5B4E6CCA02209E0DCB5CA635B89A15E271ECC760071DFD805FAA38F9729230",
},
{
256,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"00010203",
"My Tagged Application",
"20C570C31346F703C9AC36C61C03CB64C3970D0CFC787E9B79599D273A68D2F7F69D4CC3DE9D104A351689F27CF6F5951F0103F33F4F24871024D9C27773A8DD",
},
{
256,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7",
"",
"75358CF39E41494E949707927CEE0AF20A3FF553904C86B08F21CC414BCFD691589D27CF5E15369CBBFF8B9A4C2EB17800855D0235FF635DA82533EC6B759B69",
},
{
256,
"404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7",
"My Tagged Application",
"B58618F71F92E1D56C1B8C55DDD7CD188B97B4CA4D99831EB2699A837DA2E4D970FBACFDE50033AEA585F1A2708510C32D07880801BD182898FE476876FC8965",
},
}

func TestKMAC(t *testing.T) {
for i, test := range kmacTests {
key, err := hex.DecodeString(test.key)
if err != nil {
t.Errorf("error decoding KAT: %s", err)
}
tag, err := hex.DecodeString(test.tag)
if err != nil {
t.Errorf("error decoding KAT: %s", err)
}
var mac hash.Hash
if test.security == 128 {
mac = kmac.NewKMAC128(key, len(tag), []byte(test.customization))
} else {
mac = kmac.NewKMAC256(key, len(tag), []byte(test.customization))
}
data, err := hex.DecodeString(test.data)
if err != nil {
t.Errorf("error decoding KAT: %s", err)
}
mac.Write(data)
computedTag := mac.Sum(nil)
if !bytes.Equal(tag, computedTag) {
t.Errorf("#%d: got %x, want %x", i, tag, computedTag)
}
if mac.Size() != len(tag) {
t.Errorf("#%d: Size() = %x, want %x", i, mac.Size(), len(tag))
}
// Test if it works after Reset.
mac.Reset()
mac.Write(data)
computedTag = mac.Sum(nil)
if !bytes.Equal(tag, computedTag) {
t.Errorf("#%d: got %x, want %x", i, tag, computedTag)
}
// Test if Sum does not change state.
if len(data) > 1 {
mac.Reset()
mac.Write(data[0:1])
mac.Sum(nil)
mac.Write(data[1:])
computedTag = mac.Sum(nil)
if !bytes.Equal(tag, computedTag) {
t.Errorf("#%d: got %x, want %x", i, tag, computedTag)
}
}
}
}
func ExampleNewKMAC256() {
key := []byte("this is a secret key; you should generate a strong random key that's at least 32 bytes long")
tag := make([]byte, 16)
msg := []byte("The quick brown fox jumps over the lazy dog")
// Example 1: Simple KMAC
k := kmac.NewKMAC256(key, len(tag), []byte("Partition1"))
k.Write(msg)
k.Sum(tag[:0])
fmt.Println(hex.EncodeToString(tag))
// Example 2: Different customization string produces different digest
k = kmac.NewKMAC256(key, 16, []byte("Partition2"))
k.Write(msg)
k.Sum(tag[:0])
fmt.Println(hex.EncodeToString(tag))
// Output:
//3814d78758add078334b8ab9e5c4f942
//3762371e99e1e01ab17742b95c0360da
}
Loading