github.com/storacha/go-ucanto@v0.7.2/principal/rsa/signer/signer.go (about)

     1  package signer
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/rand"
     6  	"crypto/rsa"
     7  	"crypto/sha256"
     8  	"crypto/x509"
     9  	"fmt"
    10  
    11  	"github.com/multiformats/go-multibase"
    12  	"github.com/storacha/go-ucanto/did"
    13  	"github.com/storacha/go-ucanto/principal"
    14  	"github.com/storacha/go-ucanto/principal/multiformat"
    15  	"github.com/storacha/go-ucanto/principal/rsa/verifier"
    16  	"github.com/storacha/go-ucanto/ucan/crypto/signature"
    17  )
    18  
    19  const Code = 0x1305
    20  const Name = verifier.Name
    21  
    22  const SignatureCode = verifier.SignatureCode
    23  const SignatureAlgorithm = verifier.SignatureAlgorithm
    24  
    25  const keySize = 2048
    26  
    27  func Generate() (principal.Signer, error) {
    28  	priv, err := rsa.GenerateKey(rand.Reader, keySize)
    29  	if err != nil {
    30  		return nil, fmt.Errorf("generating RSA key: %w", err)
    31  	}
    32  
    33  	// Next we need to encode public key, because `RSAVerifier` uses it to
    34  	// for implementing the `DID()` method.
    35  	pubbytes := multiformat.TagWith(verifier.Code, x509.MarshalPKCS1PublicKey(&priv.PublicKey))
    36  
    37  	verif, err := verifier.Decode(pubbytes)
    38  	if err != nil {
    39  		return nil, fmt.Errorf("decoding public bytes: %w", err)
    40  	}
    41  
    42  	// Export key in Private Key Cryptography Standards (PKCS) format and extract
    43  	// the bytes corresponding to the private key, which we tag with RSA private
    44  	// key multiformat code. With both binary and actual key representation we
    45  	// create a RSASigner view.
    46  	prvbytes := multiformat.TagWith(Code, x509.MarshalPKCS1PrivateKey(priv))
    47  
    48  	return RSASigner{bytes: prvbytes, privKey: priv, verifier: verif}, nil
    49  }
    50  
    51  func Parse(str string) (principal.Signer, error) {
    52  	_, bytes, err := multibase.Decode(str)
    53  	if err != nil {
    54  		return nil, fmt.Errorf("decoding multibase string: %w", err)
    55  	}
    56  	return Decode(bytes)
    57  }
    58  
    59  func Format(signer principal.Signer) (string, error) {
    60  	return multibase.Encode(multibase.Base64pad, signer.Encode())
    61  }
    62  
    63  func Decode(b []byte) (principal.Signer, error) {
    64  	utb, err := multiformat.UntagWith(Code, b, 0)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	priv, err := x509.ParsePKCS1PrivateKey(utb)
    70  	if err != nil {
    71  		return nil, fmt.Errorf("parsing private key: %w", err)
    72  	}
    73  
    74  	pubbytes := multiformat.TagWith(verifier.Code, x509.MarshalPKCS1PublicKey(&priv.PublicKey))
    75  
    76  	verif, err := verifier.Decode(pubbytes)
    77  	if err != nil {
    78  		return nil, fmt.Errorf("decoding public bytes: %w", err)
    79  	}
    80  
    81  	return RSASigner{bytes: b, privKey: priv, verifier: verif}, nil
    82  }
    83  
    84  // FromRaw takes raw RSA private key in PKCS #1, ASN.1 DER form and tags with
    85  // the RSA signer and verifier multiformat codes, returning an RSA signer.
    86  func FromRaw(b []byte) (principal.Signer, error) {
    87  	tb := multiformat.TagWith(Code, b)
    88  	priv, err := x509.ParsePKCS1PrivateKey(b)
    89  	if err != nil {
    90  		return nil, fmt.Errorf("parsing private key: %w", err)
    91  	}
    92  	verif, err := verifier.FromRaw(x509.MarshalPKCS1PublicKey(&priv.PublicKey))
    93  	if err != nil {
    94  		return nil, fmt.Errorf("decoding public bytes: %w", err)
    95  	}
    96  	return RSASigner{bytes: tb, privKey: priv, verifier: verif}, nil
    97  }
    98  
    99  type RSASigner struct {
   100  	bytes    []byte
   101  	privKey  *rsa.PrivateKey
   102  	verifier principal.Verifier
   103  }
   104  
   105  func (s RSASigner) Code() uint64 {
   106  	return Code
   107  }
   108  
   109  func (s RSASigner) SignatureCode() uint64 {
   110  	return SignatureCode
   111  }
   112  
   113  func (s RSASigner) SignatureAlgorithm() string {
   114  	return SignatureAlgorithm
   115  }
   116  
   117  func (s RSASigner) Verifier() principal.Verifier {
   118  	return s.verifier
   119  }
   120  
   121  func (s RSASigner) DID() did.DID {
   122  	return s.verifier.DID()
   123  }
   124  
   125  func (s RSASigner) Encode() []byte {
   126  	return s.bytes
   127  }
   128  
   129  func (s RSASigner) Raw() []byte {
   130  	b, _ := multiformat.UntagWith(Code, s.bytes, 0)
   131  	return b
   132  }
   133  
   134  func (s RSASigner) Sign(msg []byte) signature.SignatureView {
   135  	hash := sha256.New()
   136  	hash.Write(msg)
   137  	digest := hash.Sum(nil)
   138  	sig, _ := rsa.SignPKCS1v15(nil, s.privKey, crypto.SHA256, digest)
   139  	return signature.NewSignatureView(signature.NewSignature(SignatureCode, sig))
   140  }