package pqcbinaryformat
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
)
var MagicBytes = []byte{0x50, 0x51, 0x43, 0x01}
const (
Version1 byte = 0x01
)
const (
AlgorithmClassical uint16 = 0x0050
AlgorithmPasswordClassical uint16 = 0x0051
AlgorithmHybrid uint16 = 0x0100
AlgorithmPostQuantum uint16 = 0x0200
AlgorithmMlKem1024 uint16 = 0x0202
AlgorithmMultiAlgorithm uint16 = 0x0201
)
const (
AlgorithmMultiKem uint16 = 0x0203
AlgorithmMultiKemTriple uint16 = 0x0204
AlgorithmQuadLayer uint16 = 0x0205
)
const (
AlgorithmLatticeCodeHybrid uint16 = 0x0206
AlgorithmPq3Stack uint16 = 0x0207
)
const (
AlgorithmMaxSecureLightweight uint16 = 0x0300
AlgorithmMaxSecurePurePQ uint16 = 0x0301
AlgorithmMaxSecureHybrid uint16 = 0x0302
AlgorithmMaxSecureStateless uint16 = 0x0303
AlgorithmMaxSecureCryptoAgile uint16 = 0x0304
AlgorithmMaxSecurePQCZK uint16 = 0x0305
AlgorithmMaxSecureHybridTransition uint16 = 0x0306
)
const (
AlgorithmFnDsa512Compact uint16 = 0x0400
AlgorithmFnDsa1024Security uint16 = 0x0401
AlgorithmFnDsaFPHardened uint16 = 0x0402
AlgorithmFnDsaDualSignature uint16 = 0x0403
AlgorithmFnDsaTransition uint16 = 0x0404
AlgorithmFnDsaZK uint16 = 0x0405
AlgorithmFnDsaZKStack uint16 = 0x0406
AlgorithmFnDsaTransitionStack uint16 = 0x0407
)
const (
AlgorithmQuantumLatticeFusion uint16 = 0x0500
AlgorithmPostZKHomomorphic uint16 = 0x0501
AlgorithmQuantumResistantConsensus uint16 = 0x0502
AlgorithmEntropyOrchestrated uint16 = 0x0503
AlgorithmLatticeCodeHybridFn uint16 = 0x0504
AlgorithmAISynthesizedCryptoAgile uint16 = 0x0505
AlgorithmExperimental uint16 = 0x0506
)
const (
AlgorithmHqc128 uint16 = 0x0600
AlgorithmHqc192 uint16 = 0x0601
AlgorithmHqc256 uint16 = 0x0602
)
const (
AlgorithmMlKem512 uint16 = 0x0700
AlgorithmMlKem768 uint16 = 0x0701
)
const (
AlgorithmMlDsa44 uint16 = 0x0800
AlgorithmMlDsa65 uint16 = 0x0801
AlgorithmMlDsa87 uint16 = 0x0802
)
const (
AlgorithmSlhDsaSha2_128s uint16 = 0x0900
AlgorithmSlhDsaSha2_128f uint16 = 0x0901
AlgorithmSlhDsaSha2_192s uint16 = 0x0902
AlgorithmSlhDsaSha2_192f uint16 = 0x0903
AlgorithmSlhDsaSha2_256s uint16 = 0x0904
AlgorithmSlhDsaSha2_256f uint16 = 0x0905
)
var algorithmNames = map[uint16]string{
AlgorithmClassical: "Classical",
AlgorithmPasswordClassical: "Password-Classical",
AlgorithmHybrid: "Hybrid",
AlgorithmPostQuantum: "Post-Quantum",
AlgorithmMlKem1024: "ML-KEM-1024",
AlgorithmMultiAlgorithm: "Multi-Algorithm",
AlgorithmMultiKem: "Multi-KEM Dual Layer",
AlgorithmMultiKemTriple: "Multi-KEM Triple Layer",
AlgorithmQuadLayer: "Quad-Layer",
AlgorithmLatticeCodeHybrid: "Lattice-Code Hybrid",
AlgorithmPq3Stack: "PQ3-Stack",
AlgorithmMaxSecureLightweight: "Max Secure: PQ Lightweight",
AlgorithmMaxSecurePurePQ: "Max Secure: Pure PQ",
AlgorithmMaxSecureHybrid: "Max Secure: Hybrid",
AlgorithmMaxSecureStateless: "Max Secure: Stateless",
AlgorithmMaxSecureCryptoAgile: "Max Secure: Crypto-Agile",
AlgorithmMaxSecurePQCZK: "Max Secure: PQC + ZK",
AlgorithmMaxSecureHybridTransition: "Max Secure: Hybrid Transition",
AlgorithmFnDsa512Compact: "FN-DSA 512: Compact",
AlgorithmFnDsa1024Security: "FN-DSA 1024: High-Security",
AlgorithmFnDsaFPHardened: "FN-DSA: Floating-Point Hardened",
AlgorithmFnDsaDualSignature: "FN-DSA: Dual Signature",
AlgorithmFnDsaTransition: "FN-DSA: Transition Stack",
AlgorithmFnDsaZK: "FN-DSA + ZK Stack",
AlgorithmFnDsaZKStack: "FN-DSA + ZK Stack Enhanced",
AlgorithmFnDsaTransitionStack: "FN-DSA: Transition Stack Enhanced",
AlgorithmQuantumLatticeFusion: "Quantum-Inspired Lattice Fusion",
AlgorithmPostZKHomomorphic: "Post-ZK Homomorphic",
AlgorithmQuantumResistantConsensus: "Quantum-Resistant Consensus",
AlgorithmEntropyOrchestrated: "Entropy-Orchestrated",
AlgorithmLatticeCodeHybridFn: "Lattice-Code Hybrid FN",
AlgorithmAISynthesizedCryptoAgile: "AI-Synthesized Crypto-Agile",
AlgorithmExperimental: "Experimental Engine",
AlgorithmHqc128: "HQC-128",
AlgorithmHqc192: "HQC-192",
AlgorithmHqc256: "HQC-256",
AlgorithmMlKem512: "ML-KEM-512",
AlgorithmMlKem768: "ML-KEM-768",
AlgorithmMlDsa44: "ML-DSA-44",
AlgorithmMlDsa65: "ML-DSA-65",
AlgorithmMlDsa87: "ML-DSA-87",
AlgorithmSlhDsaSha2_128s: "SLH-DSA-SHA2-128s",
AlgorithmSlhDsaSha2_128f: "SLH-DSA-SHA2-128f",
AlgorithmSlhDsaSha2_192s: "SLH-DSA-SHA2-192s",
AlgorithmSlhDsaSha2_192f: "SLH-DSA-SHA2-192f",
AlgorithmSlhDsaSha2_256s: "SLH-DSA-SHA2-256s",
AlgorithmSlhDsaSha2_256f: "SLH-DSA-SHA2-256f",
}
var (
ErrInvalidMagic = errors.New("invalid magic bytes")
ErrInvalidVersion = errors.New("invalid version")
ErrInvalidChecksum = errors.New("invalid checksum")
ErrInvalidLength = errors.New("invalid data length")
ErrBufferTooSmall = errors.New("buffer too small")
)
type PqcBinaryFormat struct {
Magic []byte
Version byte
AlgorithmID uint16
Flags byte
MetadataLen uint32
DataLen uint64
Metadata []byte
Data []byte
Checksum [32]byte
}
func New(algorithmID uint16, metadata, data []byte) *PqcBinaryFormat {
format := &PqcBinaryFormat{
Magic: make([]byte, 4),
Version: Version1,
AlgorithmID: algorithmID,
Flags: 0,
MetadataLen: uint32(len(metadata)),
DataLen: uint64(len(data)),
Metadata: metadata,
Data: data,
}
copy(format.Magic, MagicBytes)
return format
}
func Parse(data []byte) (*PqcBinaryFormat, error) {
if len(data) < 52 { return nil, ErrBufferTooSmall
}
format := &PqcBinaryFormat{}
offset := 0
format.Magic = data[offset : offset+4]
if !bytes.Equal(format.Magic, MagicBytes) {
return nil, ErrInvalidMagic
}
offset += 4
format.Version = data[offset]
if format.Version != Version1 {
return nil, ErrInvalidVersion
}
offset += 1
format.AlgorithmID = binary.LittleEndian.Uint16(data[offset : offset+2])
offset += 2
format.Flags = data[offset]
offset += 1
format.MetadataLen = binary.LittleEndian.Uint32(data[offset : offset+4])
offset += 4
if int(format.MetadataLen) > len(data)-offset-32 {
return nil, ErrInvalidLength
}
if format.MetadataLen > 0 {
format.Metadata = data[offset : offset+int(format.MetadataLen)]
offset += int(format.MetadataLen)
}
format.DataLen = binary.LittleEndian.Uint64(data[offset : offset+8])
offset += 8
totalLen := 52 + int(format.MetadataLen) + int(format.DataLen)
if len(data) != totalLen {
return nil, ErrInvalidLength
}
if format.DataLen > 0 {
format.Data = data[offset : offset+int(format.DataLen)]
offset += int(format.DataLen)
}
copy(format.Checksum[:], data[offset:offset+32])
offset += 32
if !format.VerifyChecksum() {
return nil, ErrInvalidChecksum
}
return format, nil
}
func (f *PqcBinaryFormat) Serialize() ([]byte, error) {
totalSize := 52 + len(f.Metadata) + len(f.Data)
buf := make([]byte, totalSize)
offset := 0
copy(buf[offset:], MagicBytes)
offset += 4
buf[offset] = f.Version
offset += 1
binary.LittleEndian.PutUint16(buf[offset:], f.AlgorithmID)
offset += 2
buf[offset] = f.Flags
offset += 1
binary.LittleEndian.PutUint32(buf[offset:], uint32(len(f.Metadata)))
offset += 4
if len(f.Metadata) > 0 {
copy(buf[offset:], f.Metadata)
offset += len(f.Metadata)
}
binary.LittleEndian.PutUint64(buf[offset:], uint64(len(f.Data)))
offset += 8
if len(f.Data) > 0 {
copy(buf[offset:], f.Data)
offset += len(f.Data)
}
checksumData := buf[:offset]
checksum := sha256.Sum256(checksumData)
copy(buf[offset:], checksum[:])
f.Checksum = checksum
return buf, nil
}
func (f *PqcBinaryFormat) VerifyChecksum() bool {
buf := new(bytes.Buffer)
buf.Write(f.Magic)
buf.WriteByte(f.Version)
algID := make([]byte, 2)
binary.LittleEndian.PutUint16(algID, f.AlgorithmID)
buf.Write(algID)
buf.WriteByte(f.Flags)
metaLen := make([]byte, 4)
binary.LittleEndian.PutUint32(metaLen, uint32(len(f.Metadata)))
buf.Write(metaLen)
buf.Write(f.Metadata)
dataLen := make([]byte, 8)
binary.LittleEndian.PutUint64(dataLen, uint64(len(f.Data)))
buf.Write(dataLen)
buf.Write(f.Data)
calculated := sha256.Sum256(buf.Bytes())
return bytes.Equal(calculated[:], f.Checksum[:])
}
func (f *PqcBinaryFormat) AlgorithmName() string {
if name, ok := algorithmNames[f.AlgorithmID]; ok {
return name
}
return fmt.Sprintf("Unknown-0x%04X", f.AlgorithmID)
}
func (f *PqcBinaryFormat) IsQuantumResistant() bool {
if f.AlgorithmID == AlgorithmClassical || f.AlgorithmID == AlgorithmPasswordClassical {
return false
}
return true
}
func (f *PqcBinaryFormat) Size() int {
return 52 + len(f.Metadata) + len(f.Data)
}
func (f *PqcBinaryFormat) String() string {
return fmt.Sprintf("PqcBinaryFormat{Version: %d, Algorithm: %s (0x%04X), MetadataLen: %d, DataLen: %d}",
f.Version, f.AlgorithmName(), f.AlgorithmID, len(f.Metadata), len(f.Data))
}