package module
Version: v0.0.5 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Dec 7, 2020 License: MIT Imports: 11 Imported by: 16


Golang Threshold Cryptography Library - RSA implementation

Go Report Card Build Status GoDoc

This library implements the cryptographic algorithms of Victor Shoup's paper Practical Threshold Signatures in the Golang programming language.

The codebase, commments and optimizations were ported from a previous implementation in C language, called tchsm-libtc. As the previous implementation, the objective of this library is to provide a set of primitives to work with.


Due to Golang extensive standard library, this implementation does not have external requirements (obviously aside of Golang, version 1.12 or above).

go get

To run the tests you just need to use go test:

go test



Package tcrsa implements the cryptographic algorithms of Victor Shoup's paper Practical Threshold Signatures, in the Golang programming language. You can find the paper defining the algorithms in

package main

import (

const exampleK = 3
const exampleL = 5

const exampleHashType = crypto.SHA256
const exampleSize = 2048
const exampleMessage = "Hello world"

func main() {
	// First we need to get the values of K and L from somewhere.
	k := uint16(exampleK)
	l := uint16(exampleL)

	// Generate keys provides to us with a list of keyShares and the key metainformation.
	keyShares, keyMeta, err := tcrsa.NewKey(exampleSize, uint16(k), uint16(l), nil)
	if err != nil {
		panic(fmt.Sprintf("%v", err))

	// Then we need to prepare the document we want to sign, so we hash it and pad it using PKCS v1.15.
	docHash := sha256.Sum256([]byte(exampleMessage))
	docPKCS1, err := tcrsa.PrepareDocumentHash(keyMeta.PublicKey.Size(), crypto.SHA256, docHash[:])
	if err != nil {
		panic(fmt.Sprintf("%v", err))

	sigShares := make(tcrsa.SigShareList, l)
	var i uint16

	// Now we sign with at least k nodes and check immediately the signature share for consistency.
	for i = 0; i < l; i++ {
		sigShares[i], err = keyShares[i].Sign(docPKCS1, exampleHashType, keyMeta)
		if err != nil {
			panic(fmt.Sprintf("%v", err))
		if err := sigShares[i].Verify(docPKCS1, keyMeta); err != nil {
			panic(fmt.Sprintf("%v", err))

	// Having all the signature shares we needed, we join them to create a real signature.
	signature, err := sigShares.Join(docPKCS1, keyMeta)
	if err != nil {
		panic(fmt.Sprintf("%v", err))

	// Finally we check the signature with Golang's crypto/rsa PKCSv1.15 verification routine.
	if err := rsa.VerifyPKCS1v15(keyMeta.PublicKey, crypto.SHA256, docHash[:], signature); err != nil {
		panic(fmt.Sprintf("%v", err))





This section is empty.


This section is empty.


func NewKey

func NewKey(bitSize int, k, l uint16, args *KeyMetaArgs) (shares KeyShareList, meta *KeyMeta, err error)

NewKey creates l key shares for a k-threshold signing scheme. The bit_size parameter is used to generate key shares with a security level equivalent to a RSA private of that size. The generated key shares have a threshold parameter of k. This means that k valid signatures are needed to sign. On success, it returns the meta information common to all the keys, and an array with all the key shares. On failure, it returns an error and invalid pointers to shares and meta information.

func PrepareDocumentHash

func PrepareDocumentHash(privateKeySize int, hashType crypto.Hash, digest []byte) ([]byte, error)

PrepareDocumentHash receives a document hash and encodes it in PKCS v1.15 for its signing. This method was copied from SignPKCS15 function from crypto/rsa on


type KeyMeta

type KeyMeta struct {
	PublicKey       *rsa.PublicKey   // RSA Public key used to verify signatures
	K               uint16           // Threshold
	L               uint16           // Total number of participants
	VerificationKey *VerificationKey // Verification Key associated to a Key Generation.

KeyMeta stores the meta information of a distributed key generation. It stores the RSA public key, the threshold value k and the total shares value l. It also has stored the verification keys for each signed share.

type KeyMetaArgs

type KeyMetaArgs struct {
	E int      // Public exponent. This value should be prime.
	P *big.Int // A prime, it should have the half of the bitsize.
	Q *big.Int // Another prime, it should have the other half of the bitsize.
	R *big.Int // A random prime but it must be coprime with P*Q.
	U *big.Int // An arbitrary random value.

KeyMetaArgs defines the initialization values for key generation. It allows to load previously computed keys. Useful for testing. Completely forbidden for production use.

type KeyShare

type KeyShare struct {
	Si []byte // S_i value of the Key Share.
	Id uint16 // ID of the key share.

KeyShare stores the Si value of a node and an unique incremental ID for the node. It's used to generate a signature share.

func (KeyShare) EqualsSi

func (keyShare KeyShare) EqualsSi(keyShare2 *KeyShare) bool

EqualsSi compares two key share S_i values and returns true if they are equal.

func (KeyShare) Sign

func (keyShare KeyShare) Sign(doc []byte, hashType crypto.Hash, info *KeyMeta) (sigShare *SigShare, err error)

Sign generates a signature share using a key share. A standard RSA signature is generated using several signature shares. The document to be signed should be prepared (hashed and padded) before using this function. It returns a SigShare with the signature of this node, or an error if the signing process failed.

func (KeyShare) ToBase64

func (keyShare KeyShare) ToBase64() string

ToBase64 transforms a Si value of a keyshare to Base64, and returns it.

type KeyShareList

type KeyShareList []*KeyShare

KeyShareList is a list of KeyShare values.

type SigShare

type SigShare struct {
	Xi []byte // Signature share.
	C  []byte // Verification value.
	Z  []byte // Verification value
	Id uint16 // ID of the node which generated the Signature Share.

SigShare represents a signature share for a document. It can be joined with other k signatures and generate a standard RSA signature.

func (SigShare) Verify

func (sigShare SigShare) Verify(doc []byte, info *KeyMeta) error

Verify verifies that a signature share was generated for the document provided and using a key related to the key metadata provided. It returns nil if the signature is valid, and an error if it is not.

type SigShareList

type SigShareList []*SigShare

SigShareList is a list of sigShares ready to be joined.

func (SigShareList) Join

func (sigShareList SigShareList) Join(document []byte, info *KeyMeta) (signature Signature, err error)

Join generates a standard RSA signature using the signature shares of the document provided. The number of signatures should be at least the number of threshold defined at key creation. It returns the RSA signature generated, or an error if the process fails.

type Signature

type Signature []byte

Signature is the completed signature of a document, created after joining k signature shares.

type VerificationKey

type VerificationKey struct {
	V []byte   // Verification value.
	U []byte   // Verification value.
	I [][]byte // An array of the verification values for the shares the nodes create when sign a document.

VerificationKey represents the data that is needed to verify a Key Share. It groups all the verification values for all the nodes in I property.

func NewVerificationKey

func NewVerificationKey(l uint16) *VerificationKey

NewVerificationKey generates an empty Verification Key structure, allocating space for l verification values in I.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL