From aa7b746a1411d291d7b19c5ff989c969a91c8b0b Mon Sep 17 00:00:00 2001 From: xtaci Date: Sun, 22 Dec 2024 19:48:36 +0800 Subject: [PATCH] add a fast PRNG for simple extension of seed, and move CreatePRNG to public function --- qpp.go | 21 ++++++++++++++++++--- qpp_test.go | 19 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/qpp.go b/qpp.go index a6924f8..eedbcf6 100644 --- a/qpp.go +++ b/qpp.go @@ -98,8 +98,8 @@ func NewQPP(seed []byte, numPads uint16) *QuantumPermutationPad { reverse(pad, rpad) } - qpp.encRand = qpp.CreatePRNG(seed) // Create default PRNG for encryption - qpp.decRand = qpp.CreatePRNG(seed) // Create default PRNG for decryption + qpp.encRand = CreatePRNG(seed) // Create default PRNG for encryption + qpp.decRand = CreatePRNG(seed) // Create default PRNG for decryption return qpp } @@ -118,7 +118,7 @@ func (qpp *QuantumPermutationPad) Decrypt(data []byte) { // CreatePRNG creates a deterministic pseudo-random number generator based on the provided seed // It uses HMAC and PBKDF2 to derive a random seed for the PRNG -func (qpp *QuantumPermutationPad) CreatePRNG(seed []byte) *Rand { +func CreatePRNG(seed []byte) *Rand { mac := hmac.New(sha256.New, seed) mac.Write([]byte(PM_SELECTOR_IDENTIFIER)) sum := mac.Sum(nil) @@ -135,6 +135,21 @@ func (qpp *QuantumPermutationPad) CreatePRNG(seed []byte) *Rand { return rd } +// FastPRNG creates a deterministic pseudo-random number generator based on the provided seed +func FastPRNG(seed []byte) *Rand { + sha := sha256.New() + sum := sha.Sum(seed) + + // Create and return PRNG + rd := &Rand{} + rd.xoshiro[0] = binary.LittleEndian.Uint64(sum[0:8]) + rd.xoshiro[1] = binary.LittleEndian.Uint64(sum[8:16]) + rd.xoshiro[2] = binary.LittleEndian.Uint64(sum[16:24]) + rd.xoshiro[3] = binary.LittleEndian.Uint64(sum[24:32]) + rd.seed64 = xoshiro256ss(&rd.xoshiro) + return rd +} + // EncryptWithPRNG encrypts the data using the Quantum Permutation Pad with a custom PRNG // This function shares the same permutation matrices func (qpp *QuantumPermutationPad) EncryptWithPRNG(data []byte, rand *Rand) { diff --git a/qpp_test.go b/qpp_test.go index 418b163..97b51b3 100644 --- a/qpp_test.go +++ b/qpp_test.go @@ -320,11 +320,11 @@ func TestEncryptionMixedPRNG(t *testing.T) { msg := make([]byte, len(original)) copy(msg, original) - rand_enc := qpp.CreatePRNG(seed) + rand_enc := CreatePRNG(seed) qpp.EncryptWithPRNG(msg, rand_enc) assert.NotEqual(t, original, msg, "not encrypted") - rand_dec := qpp.CreatePRNG(seed) + rand_dec := CreatePRNG(seed) qpp.DecryptWithPRNG(msg, rand_dec) assert.Equal(t, original, msg, "not equal") } @@ -382,3 +382,18 @@ func BenchmarkRandV2(b *testing.B) { _ = encRand.Uint32() } } + +func BenchmarkCreatePRNG(b *testing.B) { + seed := make([]byte, 32) + io.ReadFull(rand.Reader, seed) + for i := 0; i < b.N; i++ { + _ = CreatePRNG(seed) + } +} +func BenchmarkFastPRNG(b *testing.B) { + seed := make([]byte, 32) + io.ReadFull(rand.Reader, seed) + for i := 0; i < b.N; i++ { + _ = FastPRNG(seed) + } +}