From d022c293e22045a4239c6219e193dcc75782ecfd Mon Sep 17 00:00:00 2001 From: Shahriyar Jalayeri Date: Fri, 8 Nov 2024 14:39:42 +0200 Subject: [PATCH] secure-logs : add implementation of FssAgg Add implementation "Forward-secure sequential aggregate authentication.", aka FssAgg, based on the work of Ma and Tsudik : https://eprint.iacr.org/2007/052.pdf Signed-off-by: Shahriyar Jalayeri --- pkg/newlog/cmd/fssagg.go | 82 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 pkg/newlog/cmd/fssagg.go diff --git a/pkg/newlog/cmd/fssagg.go b/pkg/newlog/cmd/fssagg.go new file mode 100644 index 0000000000..d00d103481 --- /dev/null +++ b/pkg/newlog/cmd/fssagg.go @@ -0,0 +1,82 @@ +// Copyright (c) 2024 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "crypto/hmac" + "crypto/sha256" +) + +// Notes and TODOs: +// 1- save num key evolve in the batch metadata +// 2- if a batch of log reaches the server it means compromise of content integrity, stream integrity and truncation is detectable. +// 4- in the next version we can use the TPM emulated secure monotonic counter to truncation (deletion) detection. +// 5- each log entry in a batch should have seq number so we can verify it. +// 6- adding delete detection will in the next version will break logging? + +// This is based on wor of Ma and Tsudik: +// Ma, Di, and Gene Tsudik. "Forward-secure sequential aggregate authentication." +// IEEE Symposium on Security and Privacy (SP'07). IEEE, 2007. +// https://eprint.iacr.org/2007/052.pdf + +// h must be a collision-resistant one-way hash function (here using we are using SHA-256) +func h(data []byte) []byte { + h := sha256.New() + h.Write(data) + return h.Sum(nil) +} + +// hsk must be a secure MAC function h (here we using HMAC with SHA-256 and a secret key) +func hsk(key, message []byte) []byte { + mac := hmac.New(sha256.New, key) + mac.Write(message) + return mac.Sum(nil) +} + +// fssAggUpd updates key using hash of previous key +func fssAggUpd(prevKey []byte) []byte { + return h(prevKey) +} + +// FssAggSig takes the current key, aggregated signature so far and a message, +// calculates the message MAC, updated aggregated signature and updates the key +// for forward security. It returns the aggregated signature plus the updated key. +func fssAggSig(key []byte, aggMAC []byte, message []byte) ([]byte, []byte) { + var aggSig []byte + + // generate MAC for current message and aggregate current MAC with previous MACs + curMAC := hsk(key, message) + aggSig = h(append(aggMAC, curMAC...)) + + // update key for forward security + nextKey := fssAggUpd(key) + + return aggSig, nextKey +} + +// FssAggVer verifies aggregated signature over messages, accepting the initial +// secret key and the aggregate signature, returning a boolean indicating the +// verification result. +func fssAggVer(secretKey, aggSig []byte, messages [][]byte) bool { + key := secretKey + var computedAggSig []byte + + for i, message := range messages { + // generate MAC for current message + curMAC := hsk(key, message) + + // aggregate current MAC with previous MACs + if i == 0 { + computedAggSig = h(curMAC) + } else { + computedAggSig = h(append(computedAggSig, curMAC...)) + } + + // update key + key = fssAggUpd(key) + } + + // this compare is constant time, so no time leak and attack. + return hmac.Equal(computedAggSig, aggSig) +}