github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/crypto/rsa.go (about)

     1  package crypto
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/sha1"
     7  	"crypto/x509"
     8  	"encoding/base64"
     9  	"errors"
    10  )
    11  
    12  // GenerateRSAKeyPair generates a key pair that can be used for RSA. The
    13  // private key is exported as PKCS#8, and the public key is exported as PKIX,
    14  // and then encoded in base64.
    15  func GenerateRSAKeyPair() (string, []byte, error) {
    16  	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
    17  	if err != nil {
    18  		return "", nil, err
    19  	}
    20  	privExported, err := x509.MarshalPKCS8PrivateKey(privKey)
    21  	if err != nil {
    22  		return "", nil, err
    23  	}
    24  
    25  	pubKey, err := x509.MarshalPKIXPublicKey(privKey.Public())
    26  	if err != nil {
    27  		return "", nil, err
    28  	}
    29  	pub64 := base64.StdEncoding.EncodeToString(pubKey)
    30  	return pub64, privExported, nil
    31  }
    32  
    33  // EncryptWithRSA uses RSA-2048-OAEP-SHA1 to encrypt the payload, and returns a
    34  // bitwarden cipher string.
    35  func EncryptWithRSA(key string, payload []byte) (string, error) {
    36  	src, err := base64.StdEncoding.DecodeString(key)
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  	pubKey, err := x509.ParsePKIXPublicKey(src)
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  	pub, ok := pubKey.(*rsa.PublicKey)
    45  	if !ok {
    46  		return "", errors.New("Invalid public key")
    47  	}
    48  
    49  	hash := sha1.New()
    50  	rng := rand.Reader
    51  	dst, err := rsa.EncryptOAEP(hash, rng, pub, payload, nil)
    52  	if err != nil {
    53  		return "", err
    54  	}
    55  	dst64 := base64.StdEncoding.EncodeToString(dst)
    56  
    57  	// 4 means Rsa2048_OaepSha1_B64
    58  	cipherString := "4." + dst64
    59  	return cipherString, nil
    60  }