...

Source file src/gopkg.in/square/go-jose.v2/cryptosigner/cryptosigner.go

Documentation: gopkg.in/square/go-jose.v2/cryptosigner

     1  /*-
     2   * Copyright 2018 Square 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 cryptosigner implements an OpaqueSigner that wraps a "crypto".Signer
    18  //
    19  // https://godoc.org/crypto#Signer
    20  package cryptosigner
    21  
    22  import (
    23  	"crypto"
    24  	"crypto/ecdsa"
    25  	"crypto/rand"
    26  	"crypto/rsa"
    27  	"encoding/asn1"
    28  	"io"
    29  	"math/big"
    30  
    31  	"golang.org/x/crypto/ed25519"
    32  	"gopkg.in/square/go-jose.v2"
    33  )
    34  
    35  // Opaque creates an OpaqueSigner from a "crypto".Signer
    36  func Opaque(s crypto.Signer) jose.OpaqueSigner {
    37  	pk := &jose.JSONWebKey{
    38  		Key: s.Public(),
    39  	}
    40  	return &cryptoSigner{signer: s, rand: rand.Reader, pk: pk}
    41  }
    42  
    43  type cryptoSigner struct {
    44  	pk     *jose.JSONWebKey
    45  	signer crypto.Signer
    46  	rand   io.Reader
    47  }
    48  
    49  func (s *cryptoSigner) Public() *jose.JSONWebKey {
    50  	return s.pk
    51  }
    52  
    53  func (s *cryptoSigner) Algs() []jose.SignatureAlgorithm {
    54  	switch s.signer.Public().(type) {
    55  	case ed25519.PublicKey:
    56  		return []jose.SignatureAlgorithm{jose.EdDSA}
    57  	case *ecdsa.PublicKey:
    58  		// This could be more precise
    59  		return []jose.SignatureAlgorithm{jose.ES256, jose.ES384, jose.ES512}
    60  	case *rsa.PublicKey:
    61  		return []jose.SignatureAlgorithm{jose.RS256, jose.RS384, jose.RS512, jose.PS256, jose.PS384, jose.PS512}
    62  	default:
    63  		return nil
    64  	}
    65  }
    66  
    67  func (s *cryptoSigner) SignPayload(payload []byte, alg jose.SignatureAlgorithm) ([]byte, error) {
    68  	var hash crypto.Hash
    69  	switch alg {
    70  	case jose.EdDSA:
    71  	case jose.RS256, jose.PS256, jose.ES256:
    72  		hash = crypto.SHA256
    73  	case jose.RS384, jose.PS384, jose.ES384:
    74  		hash = crypto.SHA384
    75  	case jose.RS512, jose.PS512, jose.ES512:
    76  		hash = crypto.SHA512
    77  	default:
    78  		return nil, jose.ErrUnsupportedAlgorithm
    79  	}
    80  
    81  	var hashed []byte
    82  	if hash != crypto.Hash(0) {
    83  		hasher := hash.New()
    84  		if _, err := hasher.Write(payload); err != nil {
    85  			return nil, err
    86  		}
    87  		hashed = hasher.Sum(nil)
    88  	}
    89  
    90  	var (
    91  		out []byte
    92  		err error
    93  	)
    94  	switch alg {
    95  	case jose.EdDSA:
    96  		out, err = s.signer.Sign(s.rand, payload, crypto.Hash(0))
    97  	case jose.ES256, jose.ES384, jose.ES512:
    98  		var byteLen int
    99  		switch alg {
   100  		case jose.ES256:
   101  			byteLen = 32
   102  		case jose.ES384:
   103  			byteLen = 48
   104  		case jose.ES512:
   105  			byteLen = 66
   106  		}
   107  		var b []byte
   108  		b, err = s.signer.Sign(s.rand, hashed, hash)
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  
   113  		sig := struct {
   114  			R, S *big.Int
   115  		}{}
   116  		if _, err = asn1.Unmarshal(b, &sig); err != nil {
   117  			return nil, err
   118  		}
   119  
   120  		rBytes := sig.R.Bytes()
   121  		rBytesPadded := make([]byte, byteLen)
   122  		copy(rBytesPadded[byteLen-len(rBytes):], rBytes)
   123  
   124  		sBytes := sig.S.Bytes()
   125  		sBytesPadded := make([]byte, byteLen)
   126  		copy(sBytesPadded[byteLen-len(sBytes):], sBytes)
   127  
   128  		out = append(rBytesPadded, sBytesPadded...)
   129  	case jose.RS256, jose.RS384, jose.RS512:
   130  		out, err = s.signer.Sign(s.rand, hashed, hash)
   131  	case jose.PS256, jose.PS384, jose.PS512:
   132  		out, err = s.signer.Sign(s.rand, hashed, &rsa.PSSOptions{
   133  			SaltLength: rsa.PSSSaltLengthAuto,
   134  			Hash:       hash,
   135  		})
   136  	}
   137  	return out, err
   138  }
   139  

View as plain text