// 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) }
// 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 }
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 }
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 }
// 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 }
// 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, }, }) }
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 }
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) } }
// 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 }