github.com/cloudflare/circl@v1.5.0/blindsign/blindrsa/brsa.go (about)

     1  // Package blindrsa implements the RSA Blind Signature Protocol as defined in [RFC9474].
     2  //
     3  // The RSA Blind Signature protocol, and its variant RSABSSA
     4  // (RSA Blind Signature Scheme with Appendix) is a two-party protocol
     5  // between a Client and Server where they interact to compute
     6  //
     7  //	sig = Sign(sk, input_msg),
     8  //
     9  // where `input_msg = Prepare(msg)` is a prepared version of a private
    10  // message `msg` provided by the Client, and `sk` is the private signing
    11  // key provided by the server.
    12  //
    13  // # Supported Variants
    14  //
    15  // This package is compliant with the [RFC-9474] document
    16  // and supports the following variants:
    17  //   - RSABSSA-SHA384-PSS-Deterministic
    18  //   - RSABSSA-SHA384-PSSZERO-Deterministic
    19  //   - RSABSSA-SHA384-PSS-Randomized
    20  //   - RSABSSA-SHA384-PSSZERO-Randomized
    21  //
    22  // [RFC-9474]: https://www.rfc-editor.org/info/rfc9474
    23  package blindrsa
    24  
    25  import (
    26  	"crypto"
    27  	"crypto/rand"
    28  	"crypto/rsa"
    29  	"io"
    30  	"math/big"
    31  
    32  	"github.com/cloudflare/circl/blindsign/blindrsa/internal/common"
    33  	"github.com/cloudflare/circl/blindsign/blindrsa/internal/keys"
    34  )
    35  
    36  type Variant int
    37  
    38  const (
    39  	SHA384PSSRandomized        Variant = iota // RSABSSA-SHA384_PSS_Randomized
    40  	SHA384PSSZeroRandomized                   // RSABSSA-SHA384_PSSZero_Randomized
    41  	SHA384PSSDeterministic                    // RSABSSA-SHA384_PSS_Deterministic
    42  	SHA384PSSZeroDeterministic                // RSABSSA-SHA384_PSSZero_Deterministic
    43  )
    44  
    45  func (v Variant) String() string {
    46  	switch v {
    47  	case SHA384PSSRandomized:
    48  		return "RSABSSA-SHA384-PSS-Randomized"
    49  	case SHA384PSSZeroRandomized:
    50  		return "RSABSSA-SHA384-PSSZero-Randomized"
    51  	case SHA384PSSDeterministic:
    52  		return "RSABSSA-SHA384-PSS-Deterministic"
    53  	case SHA384PSSZeroDeterministic:
    54  		return "RSABSSA-SHA384-PSSZero-Deterministic"
    55  	default:
    56  		return "invalid RSABSSA variant"
    57  	}
    58  }
    59  
    60  // Client is a type that implements the client side of the blind RSA
    61  // protocol, described in https://www.rfc-editor.org/rfc/rfc9474.html#name-rsabssa-variants
    62  type Client struct {
    63  	v         Verifier
    64  	prefixLen int
    65  }
    66  
    67  func NewClient(v Variant, pk *rsa.PublicKey) (Client, error) {
    68  	verif, err := NewVerifier(v, pk)
    69  	if err != nil {
    70  		return Client{}, err
    71  	}
    72  	var prefixLen int
    73  	switch v {
    74  	case SHA384PSSDeterministic, SHA384PSSZeroDeterministic:
    75  		prefixLen = 0
    76  	case SHA384PSSRandomized, SHA384PSSZeroRandomized:
    77  		prefixLen = 32
    78  	default:
    79  		return Client{}, ErrInvalidVariant
    80  	}
    81  
    82  	return Client{verif, prefixLen}, nil
    83  }
    84  
    85  type State struct {
    86  	// The hashed and encoded message being signed
    87  	encodedMsg []byte
    88  
    89  	// Inverse of the blinding factor produced by the Verifier
    90  	rInv *big.Int
    91  }
    92  
    93  // Prepare is the process by which the message to be signed and
    94  // verified is prepared for input to the blind signing protocol.
    95  func (c Client) Prepare(random io.Reader, message []byte) ([]byte, error) {
    96  	if random == nil {
    97  		return nil, common.ErrInvalidRandomness
    98  	}
    99  
   100  	prefix := make([]byte, c.prefixLen)
   101  	_, err := io.ReadFull(random, prefix)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	return append(append([]byte{}, prefix...), message...), nil
   107  }
   108  
   109  // Blind initializes the blind RSA protocol using an input message and source of randomness.
   110  // This function fails if randomness was not provided.
   111  func (c Client) Blind(random io.Reader, preparedMessage []byte) (blindedMsg []byte, state State, err error) {
   112  	if random == nil {
   113  		return nil, State{}, common.ErrInvalidRandomness
   114  	}
   115  
   116  	salt := make([]byte, c.v.SaltLength)
   117  	_, err = io.ReadFull(random, salt)
   118  	if err != nil {
   119  		return nil, State{}, err
   120  	}
   121  
   122  	r, rInv, err := common.GenerateBlindingFactor(random, c.v.pk.N)
   123  	if err != nil {
   124  		return nil, State{}, err
   125  	}
   126  
   127  	return c.fixedBlind(preparedMessage, salt, r, rInv)
   128  }
   129  
   130  func (c Client) fixedBlind(message, salt []byte, r, rInv *big.Int) (blindedMsg []byte, state State, err error) {
   131  	encodedMsg, err := common.EncodeMessageEMSAPSS(message, c.v.pk.N, c.v.Hash.New(), salt)
   132  	if err != nil {
   133  		return nil, State{}, err
   134  	}
   135  
   136  	m := new(big.Int).SetBytes(encodedMsg)
   137  
   138  	bigE := big.NewInt(int64(c.v.pk.E))
   139  	x := new(big.Int).Exp(r, bigE, c.v.pk.N)
   140  	z := new(big.Int).Set(m)
   141  	z.Mul(z, x)
   142  	z.Mod(z, c.v.pk.N)
   143  
   144  	kLen := (c.v.pk.N.BitLen() + 7) / 8
   145  	blindedMsg = make([]byte, kLen)
   146  	z.FillBytes(blindedMsg)
   147  
   148  	return blindedMsg, State{encodedMsg, rInv}, nil
   149  }
   150  
   151  func (c Client) Finalize(state State, blindedSig []byte) ([]byte, error) {
   152  	kLen := (c.v.pk.N.BitLen() + 7) / 8
   153  	if len(blindedSig) != kLen {
   154  		return nil, common.ErrUnexpectedSize
   155  	}
   156  
   157  	z := new(big.Int).SetBytes(blindedSig)
   158  	s := new(big.Int).Set(state.rInv)
   159  	s.Mul(s, z)
   160  	s.Mod(s, c.v.pk.N)
   161  
   162  	sig := make([]byte, kLen)
   163  	s.FillBytes(sig)
   164  
   165  	err := common.VerifyBlindSignature(keys.NewBigPublicKey(c.v.pk), state.encodedMsg, sig)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	return sig, nil
   171  }
   172  
   173  // Verify verifies the input (message, signature) pair and produces an error upon failure.
   174  func (c Client) Verify(message, signature []byte) error { return c.v.Verify(message, signature) }
   175  
   176  type Verifier struct {
   177  	// Public key of the Signer
   178  	pk *rsa.PublicKey
   179  	rsa.PSSOptions
   180  }
   181  
   182  func NewVerifier(v Variant, pk *rsa.PublicKey) (Verifier, error) {
   183  	switch v {
   184  	case SHA384PSSRandomized, SHA384PSSDeterministic:
   185  		return Verifier{pk, rsa.PSSOptions{Hash: crypto.SHA384, SaltLength: crypto.SHA384.Size()}}, nil
   186  	case SHA384PSSZeroRandomized, SHA384PSSZeroDeterministic:
   187  		return Verifier{pk, rsa.PSSOptions{Hash: crypto.SHA384, SaltLength: 0}}, nil
   188  	default:
   189  		return Verifier{}, ErrInvalidVariant
   190  	}
   191  }
   192  
   193  // Verify verifies the input (message, signature) pair and produces an error upon failure.
   194  func (v Verifier) Verify(message, signature []byte) error {
   195  	return common.VerifyMessageSignature(message, signature, v.SaltLength, keys.NewBigPublicKey(v.pk), v.Hash)
   196  }
   197  
   198  // Signer structure represents the signing server in the blind RSA protocol.
   199  // It carries the raw RSA private key used for signing blinded messages.
   200  type Signer struct {
   201  	// An RSA private key
   202  	sk *rsa.PrivateKey
   203  }
   204  
   205  // NewSigner creates a new Signer for the blind RSA protocol using an RSA private key.
   206  func NewSigner(sk *rsa.PrivateKey) Signer {
   207  	return Signer{
   208  		sk: sk,
   209  	}
   210  }
   211  
   212  // BlindSign blindly computes the RSA operation using the Signer's private key on the blinded
   213  // message input, if it's of valid length, and returns an error should the function fail.
   214  //
   215  // See the specification for more details:
   216  // https://www.rfc-editor.org/rfc/rfc9474.html#name-blindsign
   217  func (signer Signer) BlindSign(data []byte) ([]byte, error) {
   218  	kLen := (signer.sk.N.BitLen() + 7) / 8
   219  	if len(data) != kLen {
   220  		return nil, common.ErrUnexpectedSize
   221  	}
   222  
   223  	m := new(big.Int).SetBytes(data)
   224  	if m.Cmp(signer.sk.N) > 0 {
   225  		return nil, common.ErrInvalidMessageLength
   226  	}
   227  
   228  	s, err := common.DecryptAndCheck(rand.Reader, keys.NewBigPrivateKey(signer.sk), m)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  
   233  	blindSig := make([]byte, kLen)
   234  	s.FillBytes(blindSig)
   235  
   236  	return blindSig, nil
   237  }
   238  
   239  var (
   240  	ErrInvalidVariant          = common.ErrInvalidVariant
   241  	ErrUnexpectedSize          = common.ErrUnexpectedSize
   242  	ErrInvalidMessageLength    = common.ErrInvalidMessageLength
   243  	ErrInvalidBlind            = common.ErrInvalidBlind
   244  	ErrInvalidRandomness       = common.ErrInvalidRandomness
   245  	ErrUnsupportedHashFunction = common.ErrUnsupportedHashFunction
   246  )