Skip to content

Latest commit

 

History

History
148 lines (114 loc) · 3.55 KB

File metadata and controls

148 lines (114 loc) · 3.55 KB

Quark

Quark is a post-quantum crypto-secure crypto library.

Why?

"Imagine that it's fifteen years from now. Somebody announces that he's built a large quantum computer. RSA is dead. DSA is dead. Elliptic curves, hyperelliptic curves, class groups, whatever, dead, dead, dead. So users are going to run around screaming and say 'Oh my God, what do we do?'..." - https://pqcrypto.org

Warning

Be careful when using cryptographic libraries implemented by non-cryptographers (including this one), as they may contain vulnerabilities.

Usage

go get github.com/karalef/quark

Sign/Verify

package main

import (
    "time"

    "github.com/karalef/quark/crypto"
    "github.com/karalef/quark/crypto/sign"
)

func main() {
    // Generate a new ML-DSA-65 key pair.
    pk, sk := crypto.Generate(sign.MLDSA65)

    msg := []byte("Hello, world!")

    signer := sk.Sign()
    signer.Write(msg)
    signature := signer.Sign()

    verifier := pk.Verify()
    verifier.Write(msg)
    ok, err := verifier.Verify(signature)
    if err != nil {
        panic("Signature is invalid (not correspond to the algorithm)")
    }
    if !ok {
        panic("Signature is wrong")
    }
}

Encrypt/Decrypt

package main

import (
	"bytes"
	"strconv"

	"github.com/karalef/quark"
	"github.com/karalef/quark/crypto"
	"github.com/karalef/quark/crypto/aead"
	"github.com/karalef/quark/crypto/extract"
	"github.com/karalef/quark/crypto/kem"
)

// generate KEM key pair
var pk, sk = crypto.Generate(kem.Kyber768)

func main() {
	s, data := Send("Hello")
	Receive(s, data, "Hello")
}

func Send(msg string) (quark.MasterKeyExchange, [][]quark.Data) {
	cipher := aead.ChaCha20Poly1305 // cipher scheme
	extSch := extract.HMAC_SHA3     // extract scheme

	// encapsulate a random shared secret and derive a master key.
	sealed, master, err := quark.NewMasterKeyExchange(pk, extSch, cipher, 16)
	if err != nil {
		panic(err)
	}

	data := make([][]quark.Data, 10)
	for i := range 10 {
		// create a nonce source to encrypt several parts with the same key.
		ns := quark.NewCounter()

		// info is a some data to expand the master key and derive a cipher key.
		info := []byte("testing " + strconv.Itoa(i))

		// expand the master key using info and create an encrypter
		enc, err := master.Encrypter(info, ns)
		if err != nil {
			panic(err)
		}

		data[i] = make([]quark.Data, 10)
		for j := range 10 {
			plaintext := []byte(msg + strconv.Itoa(i) + strconv.Itoa(j))
			ad := []byte{byte(i), byte(j)}

			// encrypt data with optional additional data
			data[i][j] = enc.EncryptData(plaintext, ad)
		}
	}

	return sealed, data
}

func Receive(s quark.MasterKeyExchange, data [][]quark.Data, must string) {
	// extract the master key from encapsulated shared secret.
	master, err := s.New(sk)
	if err != nil {
		panic(err)
	}

	for i := range len(data) {
		// info is a some data to expand the master key and derive a cipher key.
		info := []byte("testing " + strconv.Itoa(i))

		// expand the master key using info and create a cipher.
		ciph, err := master.New(info)
		if err != nil {
			panic(err)
		}

		for j := range 10 {
			mustBe := []byte(must + strconv.Itoa(i) + strconv.Itoa(j))
			ad := []byte{byte(i), byte(j)}

			// decrypt data with optional additional data.
			// DecryptDataBuf uses internal buffer to not modify the data.
			pt, err := ciph.DecryptDataBuf(data[i][j], ad)
			if err != nil {
				panic(err)
			}

			if !bytes.Equal(pt, mustBe) {
				panic("decrypted data does not match")
			}
		}
	}
}