Skip to content

Instantly share code, notes, and snippets.

@murphybytes
Last active July 15, 2017 23:54
Show Gist options
  • Save murphybytes/410fd507fb50608fa22d15431df394e8 to your computer and use it in GitHub Desktop.
Save murphybytes/410fd507fb50608fa22d15431df394e8 to your computer and use it in GitHub Desktop.
Go Factory
package main
import (
"crypto"
"crypto/rsa"
"crypto/ecdsa"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"math/big"
"github.com/pkg/errors"
)
var errSignatureCheckFailed = errors.New("signature check failed")
var errSignatureThresholdNotMet = errors.New("signature threshold not met")
var errInvalidKeyType = errors.New("invalid key type")
var errHashMismatch = errors.New("hash of file was not correct")
type verifier interface {
verify(digest []byte, key *Key, sig *Signature) error
}
type signingMethodECDSA struct{}
func newVerifier(method signingMethod) (verifier, error) {
switch method {
case methodECDSA:
return &signingMethodECDSA{}, nil
case methodRSAPKCS:
return &signingMethodRSAPKCS1v15{}, nil
case methodRSA:
return signingMethodRSA{}, nil
}
return nil, errors.Errorf("signing method %q is not supported", method)
}
func (sm *signingMethodECDSA) verify(signed []byte, key *Key, sig *Signature) error {
var publicKey crypto.PublicKey
switch key.KeyType {
case keyTypeECDSAx509:
rawBuff, err := key.base64Decoded()
if err != nil {
return errors.Wrap(err, "base 64 decoding public key")
}
pemCert, _ := pem.Decode(rawBuff)
if pemCert == nil {
return errors.New("failed to decode PEM x509 cert")
}
cert, err := x509.ParseCertificate(pemCert.Bytes)
if err != nil {
return errors.Wrap(err, "ecdsa verification")
}
publicKey = cert.PublicKey
case keyTypeECDSA:
rawBuff, err := key.base64Decoded()
if err != nil {
return errors.Wrap(err, "base 64 decoding public key")
}
publicKey, err = x509.ParsePKIXPublicKey(rawBuff)
if err != nil {
return errors.Wrap(err, "failed to parse public key in ecdsa verify")
}
default:
return errInvalidKeyType
}
ecdsaPublicKey, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("expected ecdsa public key, got something else")
}
expectedOctetLen := 2 * ((ecdsaPublicKey.Params().BitSize + 7) >> 3)
sigBuff, err := sig.base64Decoded()
if err != nil {
return errors.Wrap(err, "base 64 decoding signature failed")
}
sigLen := len(sigBuff)
if sigLen != expectedOctetLen {
return errors.New("signature length is incorrect")
}
rBuff, sBuff := sigBuff[:sigLen/2], sigBuff[sigLen/2:]
r := new(big.Int).SetBytes(rBuff)
s := new(big.Int).SetBytes(sBuff)
digest := sha256.Sum256(signed)
if !ecdsa.Verify(ecdsaPublicKey, digest[:], r, s) {
return errSignatureCheckFailed
}
return nil
}
type signingMethodRSAPKCS1v15 struct{}
func (v signingMethodRSAPKCS1v15) verify(signed []byte, key *Key, sig *Signature) error error {
// will return err if keytype is not a recognized RSA type
pubKey, err := getRSAPubKey(key)
if err != nil {
return err
}
digest := sha256.Sum256(msg)
rsaPub, ok := pubKey.(*rsa.PublicKey)
if !ok {
return errSignatureCheckFailed
}
if rsaPub.N.BitLen() < minRSAKeySizeBit {
return errSignatureCheckFailed
}
if len(sig) < minRSAKeySizeByte {
return errSignatureCheckFailed
}
if err = rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], sig); err != nil {
return errSignatureCheckFailed
}
return nil
}
type signingMethodRSA struct{}
func (v signingMethodRSA) verify(signed []byte, key *Key, sig *Signature) error {
digest := sha256.Sum256(msg)
if key.Algorithm() != data.RSAKey {
return ErrInvalidKeyType{}
}
k, _ := pem.Decode([]byte(key.Public()))
if k == nil {
return errSignatureCheckFailed
}
pub, err := x509.ParsePKIXPublicKey(k.Bytes)
if err != nil {
return errSignatureCheckFailed
}
return verifyPSS(pub, digest[:], sig)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment