blob: 28c82d14e0413c643261978ecacf252b0f08e897 [file] [log] [blame]
package keys
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/json"
"encoding/pem"
"errors"
"github.com/theupdateframework/go-tuf/data"
)
func init() {
VerifierMap.Store(data.KeyTypeRSASSA_PSS_SHA256, NewRsaVerifier)
SignerMap.Store(data.KeyTypeRSASSA_PSS_SHA256, NewRsaSigner)
}
func NewRsaVerifier() Verifier {
return &rsaVerifier{}
}
func NewRsaSigner() Signer {
return &rsaSigner{}
}
type rsaVerifier struct {
PublicKey string `json:"public"`
rsaKey *rsa.PublicKey
key *data.PublicKey
}
func (p *rsaVerifier) Public() string {
// Unique public key identifier, use a uniform encodng
r, err := x509.MarshalPKIXPublicKey(p.rsaKey)
if err != nil {
// This shouldn't happen with a valid rsa key, but fallback on the
// JSON public key string
return string(p.PublicKey)
}
return string(r)
}
func (p *rsaVerifier) Verify(msg, sigBytes []byte) error {
hash := sha256.Sum256(msg)
return rsa.VerifyPSS(p.rsaKey, crypto.SHA256, hash[:], sigBytes, &rsa.PSSOptions{})
}
func (p *rsaVerifier) MarshalPublicKey() *data.PublicKey {
return p.key
}
func (p *rsaVerifier) UnmarshalPublicKey(key *data.PublicKey) error {
if err := json.Unmarshal(key.Value, p); err != nil {
return err
}
var err error
p.rsaKey, err = parseKey(p.PublicKey)
if err != nil {
return err
}
p.key = key
return nil
}
// parseKey tries to parse a PEM []byte slice by attempting PKCS1 and PKIX in order.
func parseKey(data string) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(data))
if block == nil {
return nil, errors.New("tuf: pem decoding public key failed")
}
rsaPub, err := x509.ParsePKCS1PublicKey(block.Bytes)
if err == nil {
return rsaPub, nil
}
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err == nil {
rsaPub, ok := key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("tuf: invalid rsa key")
}
return rsaPub, nil
}
return nil, errors.New("tuf: error unmarshalling rsa key")
}
type rsaSigner struct {
*rsa.PrivateKey
}
type rsaPublic struct {
// PEM encoded public key.
PublicKey string `json:"public"`
}
func (s *rsaSigner) PublicData() *data.PublicKey {
pub, _ := x509.MarshalPKIXPublicKey(s.Public().(*rsa.PublicKey))
pubBytes := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: pub,
})
keyValBytes, _ := json.Marshal(rsaPublic{PublicKey: string(pubBytes)})
return &data.PublicKey{
Type: data.KeyTypeRSASSA_PSS_SHA256,
Scheme: data.KeySchemeRSASSA_PSS_SHA256,
Algorithms: data.HashAlgorithms,
Value: keyValBytes,
}
}
func (s *rsaSigner) SignMessage(message []byte) ([]byte, error) {
hash := sha256.Sum256(message)
return rsa.SignPSS(rand.Reader, s.PrivateKey, crypto.SHA256, hash[:], &rsa.PSSOptions{})
}
func (s *rsaSigner) ContainsID(id string) bool {
return s.PublicData().ContainsID(id)
}
func (s *rsaSigner) MarshalPrivateKey() (*data.PrivateKey, error) {
return nil, errors.New("not implemented for test")
}
func (s *rsaSigner) UnmarshalPrivateKey(key *data.PrivateKey) error {
return errors.New("not implemented for test")
}
func GenerateRsaKey() (*rsaSigner, error) {
privkey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, err
}
return &rsaSigner{privkey}, nil
}