Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add common logic to base envelope #35

Merged
merged 2 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions signature/algorithm.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package signature

import (
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
Expand Down Expand Up @@ -35,6 +36,19 @@ type KeySpec struct {
Size int
}

// Hash returns the hash function of the algorithm
func (alg Algorithm) Hash() crypto.Hash {
switch alg {
case AlgorithmPS256, AlgorithmES256:
return crypto.SHA256
case AlgorithmPS384, AlgorithmES384:
return crypto.SHA384
case AlgorithmPS512, AlgorithmES512:
return crypto.SHA512
}
return 0
}

// ExtractKeySpec extracts keySpec from the signing certificate
func ExtractKeySpec(signingCert *x509.Certificate) (KeySpec, error) {
switch key := signingCert.PublicKey.(type) {
Expand Down
17 changes: 14 additions & 3 deletions signature/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Envelope interface {
// NewEnvelopeFunc defines a function to create a new Envelope
type NewEnvelopeFunc func() Envelope

// ParseEnvelopeFunc defines a function to create a new Envelope with given
// ParseEnvelopeFunc defines a function to create a new Envelope with given
// envelope bytes
type ParseEnvelopeFunc func([]byte) (Envelope, error)

Expand All @@ -30,14 +30,25 @@ func RegisterEnvelopeType(mediaType string, newFunc NewEnvelopeFunc, parseFunc P
if newFunc == nil || parseFunc == nil {
return fmt.Errorf("required functions not provided")
}

envelopeFuncs[mediaType] = envelopeFunc{
newFunc: newFunc,
parseFunc: parseFunc,
}
return nil
}

// RegisteredEnvelopeTypes lists registered envelope media types.
func RegisteredEnvelopeTypes() []string {
types := []string{}

for envelopeType := range envelopeFuncs {
types = append(types, envelopeType)
}

return types
}

// NewEnvelope returns an envelope of given media type
func NewEnvelope(mediaType string) (Envelope, error) {
envelopeFunc, ok := envelopeFuncs[mediaType]
Expand All @@ -54,4 +65,4 @@ func ParseEnvelope(mediaType string, envelopeBytes []byte) (Envelope, error) {
return nil, fmt.Errorf("envelope is not set for type: %s", mediaType)
}
return envelopeFunc.parseFunc(envelopeBytes)
}
}
61 changes: 45 additions & 16 deletions signature/internal/base/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func (e *Envelope) Sign(req *signature.SignRequest) ([]byte, error) {
if err != nil {
return nil, err
}

e.Raw, err = e.Envelope.Sign(req)
if err != nil {
return nil, err
Expand All @@ -37,15 +38,40 @@ func (e *Envelope) Verify() (*signature.Payload, *signature.SignerInfo, error) {
return nil, nil, &signature.MalformedSignatureError{}
}

return e.Envelope.Verify()
if err := e.validatePayload(); err != nil {
return nil, nil, err
}

payload, signerInfo, err := e.Envelope.Verify()
if err != nil {
return nil, nil, err
}

if err = validatePayload(payload); err != nil {
return nil, nil, err
}

if err = validateSignerInfo(signerInfo); err != nil {
return nil, nil, err
}

return payload, signerInfo, nil
}

// Payload returns the payload to be signed.
func (e *Envelope) Payload() (*signature.Payload, error) {
if len(e.Raw) == 0 {
return nil, &signature.MalformedSignatureError{Msg: "raw signature is empty"}
}
return e.Envelope.Payload()
payload, err := e.Envelope.Payload()
if err != nil {
return nil, err
}

if err = validatePayload(payload); err != nil {
return nil, err
}
return payload, nil
}

// SignerInfo returns information about the Signature envelope.
Expand All @@ -65,10 +91,6 @@ func (e *Envelope) SignerInfo() (*signature.SignerInfo, error) {
return nil, err
}

if err := e.validatePayload(); err != nil {
return nil, err
}

return signerInfo, nil
}

Expand All @@ -92,15 +114,21 @@ func validateSignRequest(req *signature.SignRequest) error {
return err
}

if len(req.Payload.Content) == 0 {
return &signature.MalformedSignatureError{Msg: "payload not present"}
}

if req.Signer == nil {
return &signature.MalformedSignatureError{Msg: "signer is nil"}
}

return nil
certs, err := req.Signer.CertificateChain()
if err != nil {
return err
}

keySpec, err := req.Signer.KeySpec()
if err != nil {
return err
}

return validateCertificateChain(certs, req.SigningTime, keySpec.SignatureAlgorithm())
}

// validateSignerInfo performs basic set of validations on SignerInfo struct.
Expand Down Expand Up @@ -140,11 +168,12 @@ func validateSigningTime(signingTime, expireTime time.Time) error {

// validatePayload performs validation of the payload.
func validatePayload(payload *signature.Payload) error {
if len(payload.Content) == 0 {
return &signature.MalformedSignatureError{Msg: "content not present"}
}

if payload.ContentType != signature.MediaTypePayloadV1 {
switch payload.ContentType {
case signature.MediaTypePayloadV1:
if len(payload.Content) == 0 {
return &signature.MalformedSignatureError{Msg: "content not present"}
}
default:
return &signature.MalformedSignatureError{
Msg: fmt.Sprintf("payload content type: {%s} not supported", payload.ContentType),
}
Expand Down
2 changes: 1 addition & 1 deletion signature/jws/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (s *JwsSigner) Sign(digest []byte) ([]byte, error) {
if err != nil {
return nil, err
}
hasher := hash(keySpec.SignatureAlgorithm())
hasher := keySpec.SignatureAlgorithm().Hash()
h := hasher.New()
h.Write(digest)
hash := h.Sum(nil)
Expand Down
13 changes: 0 additions & 13 deletions signature/jws/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,6 @@ func mergeMaps(maps ...map[string]interface{}) map[string]interface{} {
return result
}

func hash(algorithm signature.Algorithm) crypto.Hash {
var hash crypto.Hash
switch algorithm {
case signature.AlgorithmPS256, signature.AlgorithmES256:
hash = crypto.SHA256
case signature.AlgorithmPS384, signature.AlgorithmES384:
hash = crypto.SHA384
case signature.AlgorithmPS512, signature.AlgorithmES512:
hash = crypto.SHA512
}
return hash
}

// getSigningMethod picks up a recommended algorithm for given public keys.
func getSigningMethod(key crypto.PublicKey) (jwt.SigningMethod, error) {
switch key := key.(type) {
Expand Down