// jwsEncodeJSON signs claimset using provided key and a nonce.
// The result is serialized in JSON format.
// See https://tools.ietf.org/html/rfc7515#section-7.
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, nonce string) ([]byte, error) {
	jwk, err := jwkEncode(key.Public())
	if err != nil {
		return nil, err
	}
	phead := fmt.Sprintf(`{"alg":"RS256","jwk":%s,"nonce":%q}`, jwk, nonce)
	phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
	cs, err := json.Marshal(claimset)
	if err != nil {
		return nil, err
	}
	payload := base64.RawURLEncoding.EncodeToString(cs)
	h := sha256.New()
	h.Write([]byte(phead + "." + payload))
	sig, err := key.Sign(rand.Reader, h.Sum(nil), crypto.SHA256)
	if err != nil {
		return nil, err
	}
	enc := struct {
		Protected string `json:"protected"`
		Payload   string `json:"payload"`
		Sig       string `json:"signature"`
	}{
		Protected: phead,
		Payload:   payload,
		Sig:       base64.RawURLEncoding.EncodeToString(sig),
	}
	return json.Marshal(&enc)
}
Example #2
0
// NewSignTests generates a map of test name to TestFunc that performs an opaque sign and verify.
func NewSignTests(priv crypto.Signer) map[string]testapi.TestFunc {
	tests := make(map[string]testapi.TestFunc)
	ptxt := []byte("Test Plaintext")
	r := rand.Reader
	hashes := map[string]crypto.Hash{
		"sign.md5sha1": crypto.MD5SHA1,
		"sign.sha1":    crypto.SHA1,
		"sign.sha224":  crypto.SHA224,
		"sign.sha256":  crypto.SHA256,
		"sign.sha384":  crypto.SHA384,
		"sign.sha512":  crypto.SHA512,
	}

	for hashName, h := range hashes {
		var msg []byte
		if h == crypto.MD5SHA1 {
			msg = append(hashPtxt(crypto.MD5, ptxt), hashPtxt(crypto.SHA1, ptxt)...)
		} else {
			msg = hashPtxt(h, ptxt)
		}

		tests[hashName] = func(h crypto.Hash) testapi.TestFunc {
			return func() error {
				sig, err := priv.Sign(r, msg, h)
				if err != nil {
					return err
				}

				switch pub := priv.Public().(type) {
				case *rsa.PublicKey:
					return rsa.VerifyPKCS1v15(pub, h, msg, sig)
				case *ecdsa.PublicKey:
					ecdsaSig := new(struct{ R, S *big.Int })
					asn1.Unmarshal(sig, ecdsaSig)
					if !ecdsa.Verify(pub, msg, ecdsaSig.R, ecdsaSig.S) {
						return errors.New("ecdsa verify failed")
					}
				default:
					return errors.New("unknown public key type")
				}

				return nil
			}
		}(h)
	}
	return tests
}
Example #3
0
func NewBlock(old *Block, prf PoS, ts []Transaction, signer crypto.Signer) *Block {
	oldH, err := old.Hash.MarshalBinary()
	if err != nil {
		panic(err)
	}
	prevHash := sha3.Sum256(oldH)
	h := Hash{
		Hash:  prevHash[:],
		Proof: prf,
	}

	var tsBytes []byte
	for i := range ts {
		b, err := ts[i].MarshalBinary()
		if err != nil {
			panic(err)
		}
		tsBytes = append(tsBytes, b...)
	}
	sigBytes := util.Concat([][]byte{old.Sig.Tsig, old.Sig.Ssig})

	tsig, err := signer.Sign(rand.Reader, tsBytes, crypto.SHA3_256)
	if err != nil {
		panic(err)
	}
	ssig, err := signer.Sign(rand.Reader, sigBytes, crypto.SHA3_256)
	if err != nil {
		panic(err)
	}
	sig := Signature{
		Tsig: tsig,
		Ssig: ssig,
	}

	b := Block{
		Id:    old.Id + 1,
		Hash:  h,
		Trans: ts,
		Sig:   sig,
	}
	return &b
}
Example #4
0
func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) {
	signature, err := k.Sign(rand.Reader, hashed, hash)
	if err != nil {
		return nil, err
	}

	switch alg {
	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512:
		return signature, nil

	case ECDSAP256SHA256, ECDSAP384SHA384:
		ecdsaSignature := &struct {
			R, S *big.Int
		}{}
		if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil {
			return nil, err
		}

		var intlen int
		switch alg {
		case ECDSAP256SHA256:
			intlen = 32
		case ECDSAP384SHA384:
			intlen = 48
		}

		signature := intToBytes(ecdsaSignature.R, intlen)
		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...)
		return signature, nil

	// There is no defined interface for what a DSA backed crypto.Signer returns
	case DSA, DSANSEC3SHA1:
		// 	t := divRoundUp(divRoundUp(p.PublicKey.Y.BitLen(), 8)-64, 8)
		// 	signature := []byte{byte(t)}
		// 	signature = append(signature, intToBytes(r1, 20)...)
		// 	signature = append(signature, intToBytes(s1, 20)...)
		// 	rr.Signature = signature
	}

	return nil, ErrAlg
}
Example #5
0
// jwsSign signs the digest using the given key.
// It returns ErrUnsupportedKey if the key type is unknown.
// The hash is used only for RSA keys.
func jwsSign(key crypto.Signer, hash crypto.Hash, digest []byte) ([]byte, error) {
	switch key := key.(type) {
	case *rsa.PrivateKey:
		return key.Sign(rand.Reader, digest, hash)
	case *ecdsa.PrivateKey:
		r, s, err := ecdsa.Sign(rand.Reader, key, digest)
		if err != nil {
			return nil, err
		}
		rb, sb := r.Bytes(), s.Bytes()
		size := key.Params().BitSize / 8
		if size%8 > 0 {
			size++
		}
		sig := make([]byte, size*2)
		copy(sig[size-len(rb):], rb)
		copy(sig[size*2-len(sb):], sb)
		return sig, nil
	}
	return nil, ErrUnsupportedKey
}
Example #6
0
// CreateResponse returns a DER-encoded OCSP response with the specified contents.
// The fields in the response are populated as follows:
//
// The responder cert is used to populate the ResponderName field, and the certificate
// itself is provided alongside the OCSP response signature.
//
// The issuer cert is used to puplate the IssuerNameHash and IssuerKeyHash fields.
// (SHA-1 is used for the hash function; this is not configurable.)
//
// The template is used to populate the SerialNumber, RevocationStatus, RevokedAt,
// RevocationReason, ThisUpdate, and NextUpdate fields.
//
// The ProducedAt date is automatically set to the current date, to the nearest minute.
func CreateResponse(issuer, responderCert *x509.Certificate, template Response, priv crypto.Signer) ([]byte, error) {
	var publicKeyInfo struct {
		Algorithm pkix.AlgorithmIdentifier
		PublicKey asn1.BitString
	}
	if _, err := asn1.Unmarshal(issuer.RawSubjectPublicKeyInfo, &publicKeyInfo); err != nil {
		return nil, err
	}

	h := sha1.New()
	h.Write(publicKeyInfo.PublicKey.RightAlign())
	issuerKeyHash := h.Sum(nil)

	h.Reset()
	h.Write(issuer.RawSubject)
	issuerNameHash := h.Sum(nil)

	innerResponse := singleResponse{
		CertID: certID{
			HashAlgorithm: pkix.AlgorithmIdentifier{
				Algorithm:  hashOIDs[crypto.SHA1],
				Parameters: asn1.RawValue{Tag: 5 /* ASN.1 NULL */},
			},
			NameHash:      issuerNameHash,
			IssuerKeyHash: issuerKeyHash,
			SerialNumber:  template.SerialNumber,
		},
		ThisUpdate:       template.ThisUpdate.UTC(),
		NextUpdate:       template.NextUpdate.UTC(),
		SingleExtensions: template.ExtraExtensions,
	}

	switch template.Status {
	case Good:
		innerResponse.Good = true
	case Unknown:
		innerResponse.Unknown = true
	case Revoked:
		innerResponse.Revoked = revokedInfo{
			RevocationTime: template.RevokedAt.UTC(),
			Reason:         asn1.Enumerated(template.RevocationReason),
		}
	}

	responderName := asn1.RawValue{
		Class:      2, // context-specific
		Tag:        1, // explicit tag
		IsCompound: true,
		Bytes:      responderCert.RawSubject,
	}
	tbsResponseData := responseData{
		Version:          0,
		RawResponderName: responderName,
		ProducedAt:       time.Now().Truncate(time.Minute).UTC(),
		Responses:        []singleResponse{innerResponse},
	}

	tbsResponseDataDER, err := asn1.Marshal(tbsResponseData)
	if err != nil {
		return nil, err
	}

	hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm)
	if err != nil {
		return nil, err
	}

	responseHash := hashFunc.New()
	responseHash.Write(tbsResponseDataDER)
	signature, err := priv.Sign(rand.Reader, responseHash.Sum(nil), hashFunc)
	if err != nil {
		return nil, err
	}

	response := basicResponse{
		TBSResponseData:    tbsResponseData,
		SignatureAlgorithm: signatureAlgorithm,
		Signature: asn1.BitString{
			Bytes:     signature,
			BitLength: 8 * len(signature),
		},
	}
	if template.Certificate != nil {
		response.Certificates = []asn1.RawValue{
			asn1.RawValue{FullBytes: template.Certificate.Raw},
		}
	}
	responseDER, err := asn1.Marshal(response)
	if err != nil {
		return nil, err
	}

	return asn1.Marshal(responseASN1{
		Status: asn1.Enumerated(Success),
		Response: responseBytes{
			ResponseType: idPKIXOCSPBasic,
			Response:     responseDER,
		},
	})
}
Example #7
0
func (s *Server) handle(conn *gokeyless.Conn) {
	defer conn.Close()
	s.Log.Println("Handling new connection...")
	// Continuosly read request Headers from conn and respond
	// until a connection error (Read/Write failure) is encountered.
	var connError error
	for connError == nil {
		conn.SetDeadline(time.Now().Add(time.Hour))

		var h *gokeyless.Header
		if h, connError = conn.ReadHeader(); connError != nil {
			continue
		}

		s.Log.Printf("version:%d.%d id:%d body:%s", h.MajorVers, h.MinorVers, h.ID, h.Body)

		var opts crypto.SignerOpts
		var isRSA bool
		var key crypto.Signer
		var ok bool
		switch h.Body.Opcode {
		case gokeyless.OpPing:
			connError = conn.RespondPong(h.ID, h.Body.Payload)
			continue

		case gokeyless.OpRSADecrypt:
			if key, ok = s.getKey(h.Body.SKI, h.Body.Digest); !ok {
				s.Log.Println(gokeyless.ErrKeyNotFound)
				connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
				continue
			}

			if _, ok = key.Public().(*rsa.PublicKey); !ok {
				s.Log.Printf("%s: Key is not RSA\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			rsaKey, ok := key.(crypto.Decrypter)
			if !ok {
				s.Log.Printf("%s: Key is not Decrypter\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			ptxt, err := rsaKey.Decrypt(nil, h.Body.Payload, nil)
			if err != nil {
				s.Log.Printf("%s: Decryption error: %v", gokeyless.ErrCrypto, err)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				continue
			}

			connError = conn.Respond(h.ID, ptxt)
			continue
		case gokeyless.OpRSASignMD5SHA1:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignMD5SHA1:
			opts = crypto.MD5SHA1
		case gokeyless.OpRSASignSHA1:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA1:
			opts = crypto.SHA1
		case gokeyless.OpRSASignSHA224:
		case gokeyless.OpECDSASignSHA224:
			opts = crypto.SHA224
		case gokeyless.OpRSASignSHA256:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA256:
			opts = crypto.SHA256
		case gokeyless.OpRSASignSHA384:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA384:
			opts = crypto.SHA384
		case gokeyless.OpRSASignSHA512:
			isRSA = true
			fallthrough
		case gokeyless.OpECDSASignSHA512:
			opts = crypto.SHA512
		case gokeyless.OpPong:
			fallthrough
		case gokeyless.OpResponse:
			fallthrough
		case gokeyless.OpError:
			s.Log.Printf("%s: %s is not a valid request Opcode\n", gokeyless.ErrUnexpectedOpcode, h.Body.Opcode)
			connError = conn.RespondError(h.ID, gokeyless.ErrUnexpectedOpcode)
			continue
		default:
			connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
			continue
		}

		if key, ok = s.getKey(h.Body.SKI, h.Body.Digest); !ok {
			s.Log.Println(gokeyless.ErrKeyNotFound)
			connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
			continue
		}

		// Ensure we don't perform an ECDSA sign for an RSA request.
		if _, ok := key.Public().(*rsa.PublicKey); isRSA && !ok {
			s.Log.Printf("%s: request is RSA, but key is ECDSA\n", gokeyless.ErrCrypto)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			continue
		}

		sig, err := key.Sign(rand.Reader, h.Body.Payload, opts)
		if err != nil {
			s.Log.Printf("%s: Signing error: %v\n", gokeyless.ErrCrypto, err)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			continue
		}

		connError = conn.Respond(h.ID, sig)
	}
	s.Log.Printf("Connection error: %v\n", connError)
	return
}
Example #8
0
func (s *Server) handle(conn *gokeyless.Conn) {
	defer conn.Close()
	log.Debug("Handling new connection...")
	// Continuosly read request Headers from conn and respond
	// until a connection error (Read/Write failure) is encountered.
	var connError error
	for connError == nil {
		conn.SetDeadline(time.Now().Add(time.Hour))

		var h *gokeyless.Header
		if h, connError = conn.ReadHeader(); connError != nil {
			continue
		}

		requestBegin := time.Now()
		log.Debugf("version:%d.%d id:%d body:%s", h.MajorVers, h.MinorVers, h.ID, h.Body)

		var opts crypto.SignerOpts
		var key crypto.Signer
		var ok bool
		switch h.Body.Opcode {
		case gokeyless.OpPing:
			connError = conn.RespondPong(h.ID, h.Body.Payload)
			s.stats.logRequest(requestBegin)
			continue

		case gokeyless.OpRSADecrypt:
			if key, ok = s.Keys.Get(h.Body); !ok {
				log.Error(gokeyless.ErrKeyNotFound)
				connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
				s.stats.logInvalid(requestBegin)
				continue
			}

			if _, ok = key.Public().(*rsa.PublicKey); !ok {
				log.Errorf("%s: Key is not RSA\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			rsaKey, ok := key.(crypto.Decrypter)
			if !ok {
				log.Errorf("%s: Key is not Decrypter\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			ptxt, err := rsaKey.Decrypt(nil, h.Body.Payload, nil)
			if err != nil {
				log.Errorf("%s: Decryption error: %v", gokeyless.ErrCrypto, err)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}

			connError = conn.Respond(h.ID, ptxt)
			s.stats.logRequest(requestBegin)
			continue
		case gokeyless.OpRSASignMD5SHA1, gokeyless.OpECDSASignMD5SHA1:
			opts = crypto.MD5SHA1
		case gokeyless.OpRSASignSHA1, gokeyless.OpECDSASignSHA1:
			opts = crypto.SHA1
		case gokeyless.OpRSASignSHA224, gokeyless.OpECDSASignSHA224:
			opts = crypto.SHA224
		case gokeyless.OpRSASignSHA256, gokeyless.OpECDSASignSHA256:
			opts = crypto.SHA256
		case gokeyless.OpRSASignSHA384, gokeyless.OpECDSASignSHA384:
			opts = crypto.SHA384
		case gokeyless.OpRSASignSHA512, gokeyless.OpECDSASignSHA512:
			opts = crypto.SHA512
		case gokeyless.OpActivate:
			if len(s.ActivationToken) > 0 {
				hashedToken := sha256.Sum256(s.ActivationToken)
				connError = conn.Respond(h.ID, hashedToken[:])
				s.stats.logRequest(requestBegin)
			} else {
				connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
				s.stats.logInvalid(requestBegin)
			}
			continue
		case gokeyless.OpPong, gokeyless.OpResponse, gokeyless.OpError:
			log.Errorf("%s: %s is not a valid request Opcode\n", gokeyless.ErrUnexpectedOpcode, h.Body.Opcode)
			connError = conn.RespondError(h.ID, gokeyless.ErrUnexpectedOpcode)
			s.stats.logInvalid(requestBegin)
			continue
		default:
			connError = conn.RespondError(h.ID, gokeyless.ErrBadOpcode)
			s.stats.logInvalid(requestBegin)
			continue
		}

		if key, ok = s.Keys.Get(h.Body); !ok {
			log.Error(gokeyless.ErrKeyNotFound)
			connError = conn.RespondError(h.ID, gokeyless.ErrKeyNotFound)
			s.stats.logInvalid(requestBegin)
			continue
		}

		// Ensure we don't perform an ECDSA sign for an RSA request.
		switch h.Body.Opcode {
		case gokeyless.OpRSASignMD5SHA1,
			gokeyless.OpRSASignSHA1,
			gokeyless.OpRSASignSHA224,
			gokeyless.OpRSASignSHA256,
			gokeyless.OpRSASignSHA384,
			gokeyless.OpRSASignSHA512:
			if _, ok := key.Public().(*rsa.PublicKey); !ok {
				log.Errorf("%s: request is RSA, but key isn't\n", gokeyless.ErrCrypto)
				connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
				s.stats.logInvalid(requestBegin)
				continue
			}
		}

		sig, err := key.Sign(rand.Reader, h.Body.Payload, opts)
		if err != nil {
			log.Errorf("%s: Signing error: %v\n", gokeyless.ErrCrypto, err)
			connError = conn.RespondError(h.ID, gokeyless.ErrCrypto)
			s.stats.logInvalid(requestBegin)
			continue
		}

		connError = conn.Respond(h.ID, sig)
		s.stats.logRequest(requestBegin)
	}

	if connError == io.EOF {
		log.Debug("connection closed by client")
	} else {
		log.Errorf("connection error: %v\n", connError)
	}
}
Example #9
0
// testKey performs and verifies all possible opaque private key operations.
func testKey(priv crypto.Signer) (err error) {
	ptxt := []byte("Test Plaintext")
	r := rand.Reader
	hashes := []crypto.Hash{
		crypto.MD5SHA1,
		crypto.SHA1,
		crypto.SHA224,
		crypto.SHA256,
		crypto.SHA384,
		crypto.SHA512,
	}

	for _, h := range hashes {
		var msg, sig []byte
		if h == crypto.MD5SHA1 {
			msg = append(hashPtxt(crypto.MD5, ptxt), hashPtxt(crypto.SHA1, ptxt)...)
		} else {
			msg = hashPtxt(h, ptxt)
		}

		if sig, err = priv.Sign(r, msg, h); err != nil {
			return
		}

		switch pub := priv.Public().(type) {
		case *rsa.PublicKey:
			if err = rsa.VerifyPKCS1v15(pub, h, msg, sig); err != nil {
				return
			}
		case *ecdsa.PublicKey:
			ecdsaSig := new(struct{ R, S *big.Int })
			asn1.Unmarshal(sig, ecdsaSig)
			if !ecdsa.Verify(pub, msg, ecdsaSig.R, ecdsaSig.S) {
				return errors.New("ecdsa verify failed")
			}
		default:
			return errors.New("unknown public key type")
		}
	}

	if pub, ok := priv.Public().(*rsa.PublicKey); ok {
		var c, m []byte
		if c, err = rsa.EncryptPKCS1v15(r, pub, ptxt); err != nil {
			return
		}

		var decrypter crypto.Decrypter
		if decrypter, ok = priv.(crypto.Decrypter); !ok {
			return errors.New("rsa public key but cannot decrypt")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) != 0 {
			return errors.New("rsa decrypt failed")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: len(ptxt)}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) != 0 {
			return errors.New("rsa decrypt failed")
		}

		if m, err = decrypter.Decrypt(r, c, &rsa.PKCS1v15DecryptOptions{SessionKeyLen: len(ptxt) + 1}); err != nil {
			return
		}
		if bytes.Compare(ptxt, m) == 0 {
			return errors.New("rsa decrypt suceeded despite incorrect SessionKeyLen")
		}
	}

	return nil
}
func sign(stack_ *[]*asn1.CookStackElement, location string) error {
	stack := *stack_
	if len(stack) < 3 {
		return fmt.Errorf("%vsign() called on stack with fewer than 3 elements", location)
	}
	data1, ok1 := stack[len(stack)-1].Value.([]byte)
	data2, ok2 := stack[len(stack)-2].Value.([]byte)
	data3, ok3 := stack[len(stack)-3].Value.([]byte)
	key1, ok4 := stack[len(stack)-1].Value.(crypto.Signer)
	key2, ok5 := stack[len(stack)-2].Value.(crypto.Signer)
	key3, ok6 := stack[len(stack)-3].Value.(crypto.Signer)
	algo1, ok7 := stack[len(stack)-1].Value.(map[string]interface{})
	algo2, ok8 := stack[len(stack)-2].Value.(map[string]interface{})
	algo3, ok9 := stack[len(stack)-3].Value.(map[string]interface{})
	if !((ok1 || ok2 || ok3) && (ok4 || ok5 || ok6) && (ok7 || ok8 || ok9)) {
		return fmt.Errorf("%vsign() requires the top 3 elements of the stack to be a byte-array, a key and an AlgorithmIdentifier structure", location)
	}

	var data []byte
	if ok1 {
		data = data1
	}
	if ok2 {
		data = data2
	}
	if ok3 {
		data = data3
	}

	var key crypto.Signer
	if ok4 {
		key = key1
	}
	if ok5 {
		key = key2
	}
	if ok6 {
		key = key3
	}

	var algo map[string]interface{}
	if ok7 {
		algo = algo1
	}
	if ok8 {
		algo = algo2
	}
	if ok9 {
		algo = algo3
	}

	algorithm, ok := algo["algorithm"]
	if !ok {
		return fmt.Errorf("%vsign() error: signatureAlgorithm has no \"algorithm\" member", location)
	}

	ok = false
	algooid := ""
	switch al := algorithm.(type) {
	case *asn1.Instance:
		ok = (al.Type() == "OBJECT_IDENTIFIER")
		if ok {
			algooid = al.JSON()
			algooid = algooid[2 : len(algooid)-1] // remove "$ and "
		}
	}

	if !ok {
		return fmt.Errorf("%vsign() error: \"algorithm\" not of type OBJECT IDENTIFIER", location)
	}

	var cryptohash crypto.Hash
	switch algooid {
	//md2WithRSAEncryption
	//case "1.2.840.113549.1.1.2": cryptohash = crypto.MD2

	// md5WithRSAEncryption
	case "1.2.840.113549.1.1.4":
		cryptohash = crypto.MD5

	// sha1WithRSAEncryption
	case "1.2.840.113549.1.1.5":
		cryptohash = crypto.SHA1

	// id-dsa-with-sha1
	case "1.2.840.10040.4.3":
		cryptohash = crypto.SHA1

	// id-dsa-with-sha224
	case "2.16.840.1.101.3.4.3.1":
		cryptohash = crypto.SHA224

	// id-dsa-with-sha256
	case "2.16.840.1.101.3.4.3.2":
		cryptohash = crypto.SHA256

	// ecdsa-with-SHA1
	case "1.2.840.10045.4.1":
		cryptohash = crypto.SHA1

	// ecdsa-with-SHA224
	case "1.2.840.10045.4.3.1":
		cryptohash = crypto.SHA224

	// ecdsa-with-SHA256
	case "1.2.840.10045.4.3.2":
		cryptohash = crypto.SHA256

	// ecdsa-with-SHA384
	case "1.2.840.10045.4.3.3":
		cryptohash = crypto.SHA384

	// ecdsa-with-SHA512
	case "1.2.840.10045.4.3.4":
		cryptohash = crypto.SHA512

	// sha224WithRSAEncryption
	case "1.2.840.113549.1.1.14":
		cryptohash = crypto.SHA224

	// sha256WithRSAEncryption
	case "1.2.840.113549.1.1.11":
		cryptohash = crypto.SHA256

	// sha384WithRSAEncryption
	case "1.2.840.113549.1.1.12":
		cryptohash = crypto.SHA384

	// sha512WithRSAEncryption
	case "1.2.840.113549.1.1.13":
		cryptohash = crypto.SHA512

	default:
		return fmt.Errorf("%vsign() error: Unknown signature algorithm OID \"%v\"", location, algooid)
	}

	var hashhash hash.Hash
	hashhash = cryptohash.New()
	hashhash.Write(data)
	sig, err := key.Sign(rand.Reader, hashhash.Sum(nil), cryptohash)
	if err != nil {
		return fmt.Errorf("%vsign() error: %v", location, err)
	}

	*stack_ = append(stack[0:len(stack)-3], &asn1.CookStackElement{Value: sig})
	return nil
}