Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

KarpelesLab/mldsa

Open more actions menu

Repository files navigation

mldsa

A pure Go implementation of ML-DSA (Module-Lattice Digital Signature Algorithm) as specified in FIPS 204.

ML-DSA is a post-quantum digital signature scheme standardized by NIST, designed to be secure against attacks by quantum computers.

Features

  • Pure Go implementation with no external dependencies (only standard library)
  • Supports all three security levels: ML-DSA-44, ML-DSA-65, and ML-DSA-87
  • Implements crypto.Signer and crypto.MessageSigner (Go 1.25+) interfaces
  • Simple, clean API
  • FIPS 204 compliant (validated against NIST ACVP test vectors)
  • MIT licensed

Installation

go get github.com/KarpelesLab/mldsa

Security Levels

Parameter Set Security Level Public Key Private Key Signature
ML-DSA-44 128-bit 1,312 bytes 2,560 bytes 2,420 bytes
ML-DSA-65 192-bit 1,952 bytes 4,032 bytes 3,309 bytes
ML-DSA-87 256-bit 2,592 bytes 4,896 bytes 4,627 bytes

Usage

Key Generation

package main

import (
    "crypto/rand"
    "fmt"
    "log"

    "github.com/KarpelesLab/mldsa"
)

func main() {
    // Generate a new ML-DSA-65 key pair
    key, err := mldsa.GenerateKey65(rand.Reader)
    if err != nil {
        log.Fatal(err)
    }

    // Get the public key
    publicKey := key.PublicKey()

    fmt.Printf("Public key size: %d bytes\n", len(publicKey.Bytes()))
}

Signing and Verification

package main

import (
    "crypto/rand"
    "fmt"
    "log"

    "github.com/KarpelesLab/mldsa"
)

func main() {
    // Generate key pair
    key, err := mldsa.GenerateKey65(rand.Reader)
    if err != nil {
        log.Fatal(err)
    }

    message := []byte("Hello, post-quantum world!")

    // Sign the message using crypto.Signer interface
    signature, err := key.Sign(rand.Reader, message, nil)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Signature size: %d bytes\n", len(signature))

    // Verify the signature
    publicKey := key.PublicKey()
    valid := publicKey.Verify(signature, message, nil)
    fmt.Printf("Signature valid: %v\n", valid)
}

Using Context Strings

ML-DSA supports optional context strings (up to 255 bytes) for domain separation:

context := []byte("my-application-v1")

// Sign with context using SignWithContext
signature, err := key.SignWithContext(rand.Reader, message, context)
if err != nil {
    log.Fatal(err)
}

// Or use SignerOpts with the crypto.Signer interface
opts := &mldsa.SignerOpts{Context: context}
signature, err = key.Sign(rand.Reader, message, opts)
if err != nil {
    log.Fatal(err)
}

// Verify with the same context
valid := publicKey.Verify(signature, message, context)

Key Serialization

// Serialize keys
seed := key.Bytes()              // 32-byte seed (can regenerate full key)
privateKeyBytes := key.PrivateKeyBytes()  // Full private key
publicKeyBytes := publicKey.Bytes()       // Public key

// Deserialize keys
key2, err := mldsa.NewKey65(seed)
if err != nil {
    log.Fatal(err)
}

privateKey, err := mldsa.NewPrivateKey65(privateKeyBytes)
if err != nil {
    log.Fatal(err)
}

publicKey2, err := mldsa.NewPublicKey65(publicKeyBytes)
if err != nil {
    log.Fatal(err)
}

API Reference

Key Generation Functions

// ML-DSA-44 (128-bit security)
func GenerateKey44(rand io.Reader) (*Key44, error)
func NewKey44(seed []byte) (*Key44, error)
func NewPrivateKey44(b []byte) (*PrivateKey44, error)
func NewPublicKey44(b []byte) (*PublicKey44, error)

// ML-DSA-65 (192-bit security)
func GenerateKey65(rand io.Reader) (*Key65, error)
func NewKey65(seed []byte) (*Key65, error)
func NewPrivateKey65(b []byte) (*PrivateKey65, error)
func NewPublicKey65(b []byte) (*PublicKey65, error)

// ML-DSA-87 (256-bit security)
func GenerateKey87(rand io.Reader) (*Key87, error)
func NewKey87(seed []byte) (*Key87, error)
func NewPrivateKey87(b []byte) (*PrivateKey87, error)
func NewPublicKey87(b []byte) (*PublicKey87, error)

Key Types

Each security level has three key types:

  • Key* - A full key pair (contains both private and public key, plus the original seed)
  • PrivateKey* - A standalone private key (can sign messages)
  • PublicKey* - A standalone public key (can verify signatures)

Key Methods

// Key pair methods
func (key *Key65) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
func (key *Key65) SignMessage(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error)
func (key *Key65) SignWithContext(rand io.Reader, message, context []byte) ([]byte, error)
func (key *Key65) PublicKey() *PublicKey65
func (key *Key65) Bytes() []byte           // Returns 32-byte seed
func (key *Key65) PrivateKeyBytes() []byte // Returns full private key

// Private key methods (implements crypto.Signer and crypto.MessageSigner)
func (sk *PrivateKey65) Public() crypto.PublicKey
func (sk *PrivateKey65) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)
func (sk *PrivateKey65) SignMessage(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error)
func (sk *PrivateKey65) SignWithContext(rand io.Reader, message, context []byte) ([]byte, error)
func (sk *PrivateKey65) Bytes() []byte

// Public key methods
func (pk *PublicKey65) Verify(sig, message, context []byte) bool
func (pk *PublicKey65) Bytes() []byte
func (pk *PublicKey65) Equal(other crypto.PublicKey) bool

SignerOpts

// SignerOpts implements crypto.SignerOpts for ML-DSA signing operations.
type SignerOpts struct {
    Context []byte // Optional context string (max 255 bytes)
}

func (opts *SignerOpts) HashFunc() crypto.Hash // Returns 0 (ML-DSA signs messages directly)

Constants

const (
    SeedSize = 32  // Size of the seed for key generation

    // ML-DSA-44
    PublicKeySize44  = 1312
    PrivateKeySize44 = 2560
    SignatureSize44  = 2420

    // ML-DSA-65
    PublicKeySize65  = 1952
    PrivateKeySize65 = 4032
    SignatureSize65  = 3309

    // ML-DSA-87
    PublicKeySize87  = 2592
    PrivateKeySize87 = 4896
    SignatureSize87  = 4627
)

License

MIT License - see LICENSE for details.

References

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  
Morty Proxy This is a proxified and sanitized view of the page, visit original site.