mirror of
				https://github.com/containers/podman.git
				synced 2025-11-01 02:42:11 +08:00 
			
		
		
		
	 d3f59bedb3
			
		
	
	d3f59bedb3
	
	
	
		
			
			This requires updating all import paths throughout, and a matching buildah update to interoperate. I can't figure out the reason for go.mod tracking github.com/containers/image v3.0.2+incompatible // indirect ((go mod graph) lists it as a direct dependency of libpod, but (go list -json -m all) lists it as an indirect dependency), but at least looking at the vendor subdirectory, it doesn't seem to be actually used in the built binaries. Signed-off-by: Miloslav Trmač <mitr@redhat.com>
		
			
				
	
	
		
			428 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package libtrust
 | |
| 
 | |
| import (
 | |
| 	"crypto"
 | |
| 	"crypto/rand"
 | |
| 	"crypto/rsa"
 | |
| 	"crypto/x509"
 | |
| 	"encoding/json"
 | |
| 	"encoding/pem"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"math/big"
 | |
| )
 | |
| 
 | |
| /*
 | |
|  * RSA DSA PUBLIC KEY
 | |
|  */
 | |
| 
 | |
| // rsaPublicKey implements a JWK Public Key using RSA digital signature algorithms.
 | |
| type rsaPublicKey struct {
 | |
| 	*rsa.PublicKey
 | |
| 	extended map[string]interface{}
 | |
| }
 | |
| 
 | |
| func fromRSAPublicKey(cryptoPublicKey *rsa.PublicKey) *rsaPublicKey {
 | |
| 	return &rsaPublicKey{cryptoPublicKey, map[string]interface{}{}}
 | |
| }
 | |
| 
 | |
| // KeyType returns the JWK key type for RSA keys, i.e., "RSA".
 | |
| func (k *rsaPublicKey) KeyType() string {
 | |
| 	return "RSA"
 | |
| }
 | |
| 
 | |
| // KeyID returns a distinct identifier which is unique to this Public Key.
 | |
| func (k *rsaPublicKey) KeyID() string {
 | |
| 	return keyIDFromCryptoKey(k)
 | |
| }
 | |
| 
 | |
| func (k *rsaPublicKey) String() string {
 | |
| 	return fmt.Sprintf("RSA Public Key <%s>", k.KeyID())
 | |
| }
 | |
| 
 | |
| // Verify verifyies the signature of the data in the io.Reader using this Public Key.
 | |
| // The alg parameter should be the name of the JWA digital signature algorithm
 | |
| // which was used to produce the signature and should be supported by this
 | |
| // public key. Returns a nil error if the signature is valid.
 | |
| func (k *rsaPublicKey) Verify(data io.Reader, alg string, signature []byte) error {
 | |
| 	// Verify the signature of the given date, return non-nil error if valid.
 | |
| 	sigAlg, err := rsaSignatureAlgorithmByName(alg)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("unable to verify Signature: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	hasher := sigAlg.HashID().New()
 | |
| 	_, err = io.Copy(hasher, data)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("error reading data to sign: %s", err)
 | |
| 	}
 | |
| 	hash := hasher.Sum(nil)
 | |
| 
 | |
| 	err = rsa.VerifyPKCS1v15(k.PublicKey, sigAlg.HashID(), hash, signature)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("invalid %s signature: %s", sigAlg.HeaderParam(), err)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // CryptoPublicKey returns the internal object which can be used as a
 | |
| // crypto.PublicKey for use with other standard library operations. The type
 | |
| // is either *rsa.PublicKey or *ecdsa.PublicKey
 | |
| func (k *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
 | |
| 	return k.PublicKey
 | |
| }
 | |
| 
 | |
| func (k *rsaPublicKey) toMap() map[string]interface{} {
 | |
| 	jwk := make(map[string]interface{})
 | |
| 	for k, v := range k.extended {
 | |
| 		jwk[k] = v
 | |
| 	}
 | |
| 	jwk["kty"] = k.KeyType()
 | |
| 	jwk["kid"] = k.KeyID()
 | |
| 	jwk["n"] = joseBase64UrlEncode(k.N.Bytes())
 | |
| 	jwk["e"] = joseBase64UrlEncode(serializeRSAPublicExponentParam(k.E))
 | |
| 
 | |
| 	return jwk
 | |
| }
 | |
| 
 | |
| // MarshalJSON serializes this Public Key using the JWK JSON serialization format for
 | |
| // RSA keys.
 | |
| func (k *rsaPublicKey) MarshalJSON() (data []byte, err error) {
 | |
| 	return json.Marshal(k.toMap())
 | |
| }
 | |
| 
 | |
| // PEMBlock serializes this Public Key to DER-encoded PKIX format.
 | |
| func (k *rsaPublicKey) PEMBlock() (*pem.Block, error) {
 | |
| 	derBytes, err := x509.MarshalPKIXPublicKey(k.PublicKey)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("unable to serialize RSA PublicKey to DER-encoded PKIX format: %s", err)
 | |
| 	}
 | |
| 	k.extended["kid"] = k.KeyID() // For display purposes.
 | |
| 	return createPemBlock("PUBLIC KEY", derBytes, k.extended)
 | |
| }
 | |
| 
 | |
| func (k *rsaPublicKey) AddExtendedField(field string, value interface{}) {
 | |
| 	k.extended[field] = value
 | |
| }
 | |
| 
 | |
| func (k *rsaPublicKey) GetExtendedField(field string) interface{} {
 | |
| 	v, ok := k.extended[field]
 | |
| 	if !ok {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return v
 | |
| }
 | |
| 
 | |
| func rsaPublicKeyFromMap(jwk map[string]interface{}) (*rsaPublicKey, error) {
 | |
| 	// JWK key type (kty) has already been determined to be "RSA".
 | |
| 	// Need to extract 'n', 'e', and 'kid' and check for
 | |
| 	// consistency.
 | |
| 
 | |
| 	// Get the modulus parameter N.
 | |
| 	nB64Url, err := stringFromMap(jwk, "n")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Public Key modulus: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	n, err := parseRSAModulusParam(nB64Url)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Public Key modulus: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	// Get the public exponent E.
 | |
| 	eB64Url, err := stringFromMap(jwk, "e")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Public Key exponent: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	e, err := parseRSAPublicExponentParam(eB64Url)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Public Key exponent: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	key := &rsaPublicKey{
 | |
| 		PublicKey: &rsa.PublicKey{N: n, E: e},
 | |
| 	}
 | |
| 
 | |
| 	// Key ID is optional, but if it exists, it should match the key.
 | |
| 	_, ok := jwk["kid"]
 | |
| 	if ok {
 | |
| 		kid, err := stringFromMap(jwk, "kid")
 | |
| 		if err != nil {
 | |
| 			return nil, fmt.Errorf("JWK RSA Public Key ID: %s", err)
 | |
| 		}
 | |
| 		if kid != key.KeyID() {
 | |
| 			return nil, fmt.Errorf("JWK RSA Public Key ID does not match: %s", kid)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if _, ok := jwk["d"]; ok {
 | |
| 		return nil, fmt.Errorf("JWK RSA Public Key cannot contain private exponent")
 | |
| 	}
 | |
| 
 | |
| 	key.extended = jwk
 | |
| 
 | |
| 	return key, nil
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * RSA DSA PRIVATE KEY
 | |
|  */
 | |
| 
 | |
| // rsaPrivateKey implements a JWK Private Key using RSA digital signature algorithms.
 | |
| type rsaPrivateKey struct {
 | |
| 	rsaPublicKey
 | |
| 	*rsa.PrivateKey
 | |
| }
 | |
| 
 | |
| func fromRSAPrivateKey(cryptoPrivateKey *rsa.PrivateKey) *rsaPrivateKey {
 | |
| 	return &rsaPrivateKey{
 | |
| 		*fromRSAPublicKey(&cryptoPrivateKey.PublicKey),
 | |
| 		cryptoPrivateKey,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // PublicKey returns the Public Key data associated with this Private Key.
 | |
| func (k *rsaPrivateKey) PublicKey() PublicKey {
 | |
| 	return &k.rsaPublicKey
 | |
| }
 | |
| 
 | |
| func (k *rsaPrivateKey) String() string {
 | |
| 	return fmt.Sprintf("RSA Private Key <%s>", k.KeyID())
 | |
| }
 | |
| 
 | |
| // Sign signs the data read from the io.Reader using a signature algorithm supported
 | |
| // by the RSA private key. If the specified hashing algorithm is supported by
 | |
| // this key, that hash function is used to generate the signature otherwise the
 | |
| // the default hashing algorithm for this key is used. Returns the signature
 | |
| // and the name of the JWK signature algorithm used, e.g., "RS256", "RS384",
 | |
| // "RS512".
 | |
| func (k *rsaPrivateKey) Sign(data io.Reader, hashID crypto.Hash) (signature []byte, alg string, err error) {
 | |
| 	// Generate a signature of the data using the internal alg.
 | |
| 	sigAlg := rsaPKCS1v15SignatureAlgorithmForHashID(hashID)
 | |
| 	hasher := sigAlg.HashID().New()
 | |
| 
 | |
| 	_, err = io.Copy(hasher, data)
 | |
| 	if err != nil {
 | |
| 		return nil, "", fmt.Errorf("error reading data to sign: %s", err)
 | |
| 	}
 | |
| 	hash := hasher.Sum(nil)
 | |
| 
 | |
| 	signature, err = rsa.SignPKCS1v15(rand.Reader, k.PrivateKey, sigAlg.HashID(), hash)
 | |
| 	if err != nil {
 | |
| 		return nil, "", fmt.Errorf("error producing signature: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	alg = sigAlg.HeaderParam()
 | |
| 
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // CryptoPrivateKey returns the internal object which can be used as a
 | |
| // crypto.PublicKey for use with other standard library operations. The type
 | |
| // is either *rsa.PublicKey or *ecdsa.PublicKey
 | |
| func (k *rsaPrivateKey) CryptoPrivateKey() crypto.PrivateKey {
 | |
| 	return k.PrivateKey
 | |
| }
 | |
| 
 | |
| func (k *rsaPrivateKey) toMap() map[string]interface{} {
 | |
| 	k.Precompute() // Make sure the precomputed values are stored.
 | |
| 	jwk := k.rsaPublicKey.toMap()
 | |
| 
 | |
| 	jwk["d"] = joseBase64UrlEncode(k.D.Bytes())
 | |
| 	jwk["p"] = joseBase64UrlEncode(k.Primes[0].Bytes())
 | |
| 	jwk["q"] = joseBase64UrlEncode(k.Primes[1].Bytes())
 | |
| 	jwk["dp"] = joseBase64UrlEncode(k.Precomputed.Dp.Bytes())
 | |
| 	jwk["dq"] = joseBase64UrlEncode(k.Precomputed.Dq.Bytes())
 | |
| 	jwk["qi"] = joseBase64UrlEncode(k.Precomputed.Qinv.Bytes())
 | |
| 
 | |
| 	otherPrimes := k.Primes[2:]
 | |
| 
 | |
| 	if len(otherPrimes) > 0 {
 | |
| 		otherPrimesInfo := make([]interface{}, len(otherPrimes))
 | |
| 		for i, r := range otherPrimes {
 | |
| 			otherPrimeInfo := make(map[string]string, 3)
 | |
| 			otherPrimeInfo["r"] = joseBase64UrlEncode(r.Bytes())
 | |
| 			crtVal := k.Precomputed.CRTValues[i]
 | |
| 			otherPrimeInfo["d"] = joseBase64UrlEncode(crtVal.Exp.Bytes())
 | |
| 			otherPrimeInfo["t"] = joseBase64UrlEncode(crtVal.Coeff.Bytes())
 | |
| 			otherPrimesInfo[i] = otherPrimeInfo
 | |
| 		}
 | |
| 		jwk["oth"] = otherPrimesInfo
 | |
| 	}
 | |
| 
 | |
| 	return jwk
 | |
| }
 | |
| 
 | |
| // MarshalJSON serializes this Private Key using the JWK JSON serialization format for
 | |
| // RSA keys.
 | |
| func (k *rsaPrivateKey) MarshalJSON() (data []byte, err error) {
 | |
| 	return json.Marshal(k.toMap())
 | |
| }
 | |
| 
 | |
| // PEMBlock serializes this Private Key to DER-encoded PKIX format.
 | |
| func (k *rsaPrivateKey) PEMBlock() (*pem.Block, error) {
 | |
| 	derBytes := x509.MarshalPKCS1PrivateKey(k.PrivateKey)
 | |
| 	k.extended["keyID"] = k.KeyID() // For display purposes.
 | |
| 	return createPemBlock("RSA PRIVATE KEY", derBytes, k.extended)
 | |
| }
 | |
| 
 | |
| func rsaPrivateKeyFromMap(jwk map[string]interface{}) (*rsaPrivateKey, error) {
 | |
| 	// The JWA spec for RSA Private Keys (draft rfc section 5.3.2) states that
 | |
| 	// only the private key exponent 'd' is REQUIRED, the others are just for
 | |
| 	// signature/decryption optimizations and SHOULD be included when the JWK
 | |
| 	// is produced. We MAY choose to accept a JWK which only includes 'd', but
 | |
| 	// we're going to go ahead and not choose to accept it without the extra
 | |
| 	// fields. Only the 'oth' field will be optional (for multi-prime keys).
 | |
| 	privateExponent, err := parseRSAPrivateKeyParamFromMap(jwk, "d")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key exponent: %s", err)
 | |
| 	}
 | |
| 	firstPrimeFactor, err := parseRSAPrivateKeyParamFromMap(jwk, "p")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err)
 | |
| 	}
 | |
| 	secondPrimeFactor, err := parseRSAPrivateKeyParamFromMap(jwk, "q")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err)
 | |
| 	}
 | |
| 	firstFactorCRT, err := parseRSAPrivateKeyParamFromMap(jwk, "dp")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err)
 | |
| 	}
 | |
| 	secondFactorCRT, err := parseRSAPrivateKeyParamFromMap(jwk, "dq")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err)
 | |
| 	}
 | |
| 	crtCoeff, err := parseRSAPrivateKeyParamFromMap(jwk, "qi")
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("JWK RSA Private Key CRT coefficient: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	var oth interface{}
 | |
| 	if _, ok := jwk["oth"]; ok {
 | |
| 		oth = jwk["oth"]
 | |
| 		delete(jwk, "oth")
 | |
| 	}
 | |
| 
 | |
| 	// JWK key type (kty) has already been determined to be "RSA".
 | |
| 	// Need to extract the public key information, then extract the private
 | |
| 	// key values.
 | |
| 	publicKey, err := rsaPublicKeyFromMap(jwk)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	privateKey := &rsa.PrivateKey{
 | |
| 		PublicKey: *publicKey.PublicKey,
 | |
| 		D:         privateExponent,
 | |
| 		Primes:    []*big.Int{firstPrimeFactor, secondPrimeFactor},
 | |
| 		Precomputed: rsa.PrecomputedValues{
 | |
| 			Dp:   firstFactorCRT,
 | |
| 			Dq:   secondFactorCRT,
 | |
| 			Qinv: crtCoeff,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	if oth != nil {
 | |
| 		// Should be an array of more JSON objects.
 | |
| 		otherPrimesInfo, ok := oth.([]interface{})
 | |
| 		if !ok {
 | |
| 			return nil, errors.New("JWK RSA Private Key: Invalid other primes info: must be an array")
 | |
| 		}
 | |
| 		numOtherPrimeFactors := len(otherPrimesInfo)
 | |
| 		if numOtherPrimeFactors == 0 {
 | |
| 			return nil, errors.New("JWK RSA Privake Key: Invalid other primes info: must be absent or non-empty")
 | |
| 		}
 | |
| 		otherPrimeFactors := make([]*big.Int, numOtherPrimeFactors)
 | |
| 		productOfPrimes := new(big.Int).Mul(firstPrimeFactor, secondPrimeFactor)
 | |
| 		crtValues := make([]rsa.CRTValue, numOtherPrimeFactors)
 | |
| 
 | |
| 		for i, val := range otherPrimesInfo {
 | |
| 			otherPrimeinfo, ok := val.(map[string]interface{})
 | |
| 			if !ok {
 | |
| 				return nil, errors.New("JWK RSA Private Key: Invalid other prime info: must be a JSON object")
 | |
| 			}
 | |
| 
 | |
| 			otherPrimeFactor, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "r")
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("JWK RSA Private Key prime factor: %s", err)
 | |
| 			}
 | |
| 			otherFactorCRT, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "d")
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("JWK RSA Private Key CRT exponent: %s", err)
 | |
| 			}
 | |
| 			otherCrtCoeff, err := parseRSAPrivateKeyParamFromMap(otherPrimeinfo, "t")
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("JWK RSA Private Key CRT coefficient: %s", err)
 | |
| 			}
 | |
| 
 | |
| 			crtValue := crtValues[i]
 | |
| 			crtValue.Exp = otherFactorCRT
 | |
| 			crtValue.Coeff = otherCrtCoeff
 | |
| 			crtValue.R = productOfPrimes
 | |
| 			otherPrimeFactors[i] = otherPrimeFactor
 | |
| 			productOfPrimes = new(big.Int).Mul(productOfPrimes, otherPrimeFactor)
 | |
| 		}
 | |
| 
 | |
| 		privateKey.Primes = append(privateKey.Primes, otherPrimeFactors...)
 | |
| 		privateKey.Precomputed.CRTValues = crtValues
 | |
| 	}
 | |
| 
 | |
| 	key := &rsaPrivateKey{
 | |
| 		rsaPublicKey: *publicKey,
 | |
| 		PrivateKey:   privateKey,
 | |
| 	}
 | |
| 
 | |
| 	return key, nil
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *	Key Generation Functions.
 | |
|  */
 | |
| 
 | |
| func generateRSAPrivateKey(bits int) (k *rsaPrivateKey, err error) {
 | |
| 	k = new(rsaPrivateKey)
 | |
| 	k.PrivateKey, err = rsa.GenerateKey(rand.Reader, bits)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	k.rsaPublicKey.PublicKey = &k.PrivateKey.PublicKey
 | |
| 	k.extended = make(map[string]interface{})
 | |
| 
 | |
| 	return
 | |
| }
 | |
| 
 | |
| // GenerateRSA2048PrivateKey generates a key pair using 2048-bit RSA.
 | |
| func GenerateRSA2048PrivateKey() (PrivateKey, error) {
 | |
| 	k, err := generateRSAPrivateKey(2048)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("error generating RSA 2048-bit key: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	return k, nil
 | |
| }
 | |
| 
 | |
| // GenerateRSA3072PrivateKey generates a key pair using 3072-bit RSA.
 | |
| func GenerateRSA3072PrivateKey() (PrivateKey, error) {
 | |
| 	k, err := generateRSAPrivateKey(3072)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("error generating RSA 3072-bit key: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	return k, nil
 | |
| }
 | |
| 
 | |
| // GenerateRSA4096PrivateKey generates a key pair using 4096-bit RSA.
 | |
| func GenerateRSA4096PrivateKey() (PrivateKey, error) {
 | |
| 	k, err := generateRSAPrivateKey(4096)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("error generating RSA 4096-bit key: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	return k, nil
 | |
| }
 |