...

Source file src/github.com/sassoftware/relic/lib/x509tools/util.go

Documentation: github.com/sassoftware/relic/lib/x509tools

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    15  //
    16  
    17  package x509tools
    18  
    19  import (
    20  	"crypto"
    21  	"crypto/ecdsa"
    22  	"crypto/rand"
    23  	"crypto/rsa"
    24  	"crypto/sha1"
    25  	"crypto/x509"
    26  	"crypto/x509/pkix"
    27  	"encoding/asn1"
    28  	"errors"
    29  	"io"
    30  	"math/big"
    31  )
    32  
    33  // Make a random 12 byte big.Int
    34  func MakeSerial() *big.Int {
    35  	blob := make([]byte, 12)
    36  	if _, err := io.ReadFull(rand.Reader, blob); err != nil {
    37  		return nil
    38  	}
    39  	return new(big.Int).SetBytes(blob)
    40  }
    41  
    42  // Choose a X509 signature algorithm suitable for the specified public key
    43  func X509SignatureAlgorithm(pub crypto.PublicKey) x509.SignatureAlgorithm {
    44  	switch pub.(type) {
    45  	case *rsa.PublicKey:
    46  		if ArgRSAPSS {
    47  			return x509.SHA256WithRSAPSS
    48  		}
    49  		return x509.SHA256WithRSA
    50  	case *ecdsa.PublicKey:
    51  		return x509.ECDSAWithSHA256
    52  	default:
    53  		return x509.UnknownSignatureAlgorithm
    54  	}
    55  }
    56  
    57  type pkixPublicKey struct {
    58  	Algo      pkix.AlgorithmIdentifier
    59  	BitString asn1.BitString
    60  }
    61  
    62  // Calculcate subject key identifier from a public key per RFC 3280
    63  func SubjectKeyID(pub crypto.PublicKey) ([]byte, error) {
    64  	der, err := x509.MarshalPKIXPublicKey(pub)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  	// extract the raw "bit string" part of the public key bytes
    69  	var pki pkixPublicKey
    70  	if rest, err := asn1.Unmarshal(der, &pki); err != nil {
    71  		return nil, err
    72  	} else if len(rest) != 0 {
    73  		return nil, errors.New("trailing garbage on public key")
    74  	}
    75  	digest := sha1.Sum(pki.BitString.RightAlign())
    76  	return digest[:], nil
    77  }
    78  
    79  // Test whether two public or private keys have the same public key
    80  func SameKey(pub1, pub2 interface{}) bool {
    81  	if privkey, ok := pub1.(crypto.Signer); ok {
    82  		pub1 = privkey.Public()
    83  	}
    84  	if privkey, ok := pub2.(crypto.Signer); ok {
    85  		pub2 = privkey.Public()
    86  	}
    87  	switch key1 := pub1.(type) {
    88  	case *rsa.PublicKey:
    89  		key2, ok := pub2.(*rsa.PublicKey)
    90  		return ok && key1.E == key2.E && key1.N.Cmp(key2.N) == 0
    91  	case *ecdsa.PublicKey:
    92  		key2, ok := pub2.(*ecdsa.PublicKey)
    93  		return ok && key1.X.Cmp(key2.X) == 0 && key1.Y.Cmp(key2.Y) == 0
    94  	default:
    95  		return false
    96  	}
    97  }
    98  
    99  // Verify an RSA or ECDSA signature
   100  func Verify(pub interface{}, hash crypto.Hash, hashed []byte, sig []byte) error {
   101  	switch pubk := pub.(type) {
   102  	case *rsa.PublicKey:
   103  		return rsa.VerifyPKCS1v15(pubk, hash, hashed, sig)
   104  	case *ecdsa.PublicKey:
   105  		esig, err := UnmarshalEcdsaSignature(sig)
   106  		if err != nil {
   107  			return err
   108  		}
   109  		if !ecdsa.Verify(pubk, hashed, esig.R, esig.S) {
   110  			return errors.New("ECDSA verification failed")
   111  		}
   112  		return nil
   113  	}
   114  	return errors.New("unsupported public key algorithm")
   115  }
   116  
   117  // Determine the type of a public or private key
   118  func GetPublicKeyAlgorithm(key interface{}) x509.PublicKeyAlgorithm {
   119  	if privkey, ok := key.(crypto.Signer); ok {
   120  		key = privkey.Public()
   121  	}
   122  	switch key.(type) {
   123  	case *rsa.PublicKey:
   124  		return x509.RSA
   125  	case *ecdsa.PublicKey:
   126  		return x509.ECDSA
   127  	default:
   128  		return x509.UnknownPublicKeyAlgorithm
   129  	}
   130  }
   131  

View as plain text