// Sign the given hex-endcoded hash checksum and return a Signature // @@TODO Remove this -- undeeded func (pk PrivateKey) SignSHA256(hexbytes []byte) (Signature, error) { if hex.DecodedLen(len(hexbytes)) != sha256.Size { return nil, ErrPrivateKeySHA256 } // Decode hex bytes into raw bytes decodedBytes := make([]byte, hex.DecodedLen(len(hexbytes))) _, err := hex.Decode(decodedBytes, hexbytes) if err != nil { return nil, errors.Wrap(err, ErrPrivateKeySHA256) } // Get the rsa cryptokey for signing cryptoKey, err := pk.GetCryptoKey() if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } // Compute the signature and return the results rawSignature, err := rsa.SignPKCS1v15(rand.Reader, cryptoKey, crypto.SHA256, decodedBytes) if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } return Signature(rawSignature), nil }
func (w *worker) process() { go func() { // Do the HTTP GET and create the response object var resp Response httpresp, err := w.client.Get(w.url) if httpresp != nil { resp = Response{Response: httpresp} } else { resp = Response{} } resp.URL = w.url resp.Crawler = w.crawler if err != nil { resp.Err = errors.Wrap(err, ErrReqFailed) w.crawler.Handler(&resp) w.sendResults(nil, resp.Err) return } // Check headers using HeaderCheck if err = w.crawler.CheckHeader(w.crawler, w.url, resp.StatusCode, resp.Header); err != nil { resp.Err = errors.Wrap(err, ErrHeaderRejected) w.crawler.Handler(&resp) resp.Body.Close() w.sendResults(nil, resp.Err) return } // Read the body resp.bytes, err = ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { resp.Err = errors.Wrap(err, ErrBodyRead) w.crawler.Handler(&resp) w.sendResults(nil, resp.Err) return } // Replace the body with a readCloser that reads from bytes resp.Body = &readCloser{bytes.NewReader(resp.bytes)} // Process the handler w.crawler.Handler(&resp) resp.Body = &readCloser{bytes.NewReader(resp.bytes)} // Find links and finish newurls := make([]string, 0) for _, url := range w.crawler.LinkFinder(&resp) { if err := w.crawler.CheckURL(w.crawler, url); err == nil { newurls = append(newurls, url) } } // We're done, return the results w.sendResults(newurls, nil) }() }
// Sign the given bytes using naive RSA signing (no hash or padding) and return a Signature using // This is compatible with blinded messages and blind signatures func (pk PrivateKey) SignRawBytes(bytes []byte) (Signature, error) { cryptoKey, err := pk.GetCryptoKey() if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } rawSignature, err := rsa.SignPKCS1v15(rand.Reader, cryptoKey, 0, bytes) if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } return Signature(rawSignature), nil }
// Verify that the signature crytpographically signs the given message using the given public key // This message does not verify using a hash function or padding but verifies using naive RSA verification func (sig Signature) VerifyRawSignature(pk PublicKey, message []byte) error { pubkey, err := pk.GetCryptoKey() if err != nil { return errors.Wrap(err, ErrSignatureVerify) } err = rsa.VerifyPKCS1v15(pubkey, 0, message, sig.Bytes()) if err != nil { return errors.Wrap(err, ErrSignatureVerify) } return err }
// Sign the blinded ballot hash attached to the Signature Request. // Despite the fact that we sign the SHA256 hash of the ballot, we do not use RSA standard SHA256 hashing and padding // Instead we do use naive RSA signing to sign the raw signature on the raw hash to ensure compatibility with blinding schemes. func (sigReq *SignatureRequest) SignBallot(priv PrivateKey) (Signature, error) { rawHash := make([]byte, hex.DecodedLen(len(sigReq.BallotHash))) _, err := hex.Decode(rawHash, sigReq.BallotHash) if err != nil { return nil, errors.Wrap(err, ErrSignatureRequestSignBallot) } sig, err := priv.SignRawBytes(rawHash) if err != nil { return nil, errors.Wrap(err, ErrSignatureRequestSignBallot) } return sig, nil }
// Sign the given bytes and return a Signature // This will use SHA256 as the signing hash function func (pk PrivateKey) SignBytes(bytes []byte) (Signature, error) { h := sha256.New() h.Write(bytes) cryptoKey, err := pk.GetCryptoKey() if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } rawSignature, err := rsa.SignPKCS1v15(rand.Reader, cryptoKey, crypto.SHA256, h.Sum(nil)) if err != nil { return nil, errors.Wrap(err, ErrPrivatKeySign) } return Signature(rawSignature), nil }
// Verify that the signature crytpographically signs the given message using the given public key func (sig Signature) VerifySignature(pk PublicKey, message []byte) error { pubkey, err := pk.GetCryptoKey() if err != nil { return errors.Wrap(err, ErrSignatureVerify) } hash := sha256.New() hash.Write(message) err = rsa.VerifyPKCS1v15(pubkey, crypto.SHA256, hash.Sum(nil), sig.Bytes()) if err != nil { return errors.Wrap(err, ErrSignatureVerify) } return err }
// Parse the PrivateKey (which is stored as a der encoded key) into a rsa.PrivateKey object, ready to be used for crypto functions func (pk PrivateKey) GetCryptoKey() (*rsa.PrivateKey, error) { privkey, err := x509.ParsePKCS1PrivateKey(pk.Bytes()) if err != nil { return nil, errors.Wrap(err, ErrPrivatKeyCryptoKey) } return privkey, nil }
// Generate a new PrivateKey func GeneratePrivateKey(keySize int) (PrivateKey, error) { cryptoKey, err := rsa.GenerateKey(rand.Reader, keySize) if err != nil { return nil, errors.Wrap(err, ErrPrivatKeyGenerate) } return NewPrivateKeyFromCryptoKey(cryptoKey), nil }
// Parse the PublicKey (which is stored as a der encoded key) into a rsa.PublicKey object, ready to be used for crypto functions func (pk PublicKey) GetCryptoKey() (*rsa.PublicKey, error) { pubkey, err := x509.ParsePKIXPublicKey(pk.Bytes()) if err != nil { return nil, errors.Wrap(err, ErrPublicKeyCryptoKey) } return pubkey.(*rsa.PublicKey), nil }
// Get the number of bits in the key func (pk PublicKey) KeyLength() (int, error) { pubkey, err := pk.GetCryptoKey() if err != nil { return 0, errors.Wrap(err, ErrPublicKeyLen) } return pubkey.N.BitLen(), nil }
// Create a new PrivateKey from a pem.Block // This function also performs error checking to make sure the key is valid. func NewPrivateKeyFromBlock(PEMBlock *pem.Block) (PrivateKey, error) { if PEMBlock.Type != "RSA PRIVATE KEY" { return nil, errors.Wraps(ErrPrivatKeyWrongType, "Found "+PEMBlock.Type) } _, err := x509.ParsePKCS1PrivateKey(PEMBlock.Bytes) if err != nil { return nil, errors.Wrap(ErrPrivatKeyInvalidPEM, err) } return PrivateKey(PEMBlock.Bytes), nil }
// Create a new signature from a base64 encoded item, as we would get in a PUT or POST request //@@TODO: Test to make sure "Signature too short" is working as expected func NewSignature(Base64Signature []byte) (Signature, error) { dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(Base64Signature))) n, err := base64.StdEncoding.Decode(dbuf, Base64Signature) if err != nil { return nil, errors.Wrap(err, ErrSignatureBase64) } if n < 128 { return nil, ErrSignatureTooShort } sig := dbuf[:n] return Signature(sig), nil }
func NewUserFromBlock(PEMBlock *pem.Block) (*User, error) { var ( err error publicKey PublicKey perms []string ) if PEMBlock.Type != "PUBLIC KEY" { return nil, errors.Wraps(ErrUserBlockNotFound, "Unexpected "+PEMBlock.Type) } publicCryptoKey, err := x509.ParsePKIXPublicKey(PEMBlock.Bytes) if err != nil { return nil, errors.Wrap(err, ErrUserInvalidPEM) } publicKey, err = NewPublicKeyFromCryptoKey(publicCryptoKey.(*rsa.PublicKey)) if err != nil { return nil, err } permString, ok := PEMBlock.Headers["perms"] if !ok || permString == "" { return nil, ErrUserPermsNotFound } permsRaw := strings.Split(permString, ",") for _, val := range permsRaw { trimmed := strings.TrimSpace(val) if trimmed == "" { return nil, ErrUserPermsInvalid } perms = append(perms, trimmed) } // All checks pass return &User{ publicKey, perms, PEMBlock.Headers, }, nil }
// Create a new PublicKey from a base64 encoded item, as we would get in a PUT or POST request // This function also performs error checking to make sure the key is valid. func NewPublicKey(base64PublicKey []byte) (PublicKey, error) { decodedLen := base64.StdEncoding.DecodedLen(len(base64PublicKey)) dbuf := make([]byte, decodedLen) n, err := base64.StdEncoding.Decode(dbuf, base64PublicKey) if err != nil { return nil, errors.Wrap(err, ErrPublicKeyBase64) } pk := PublicKey(dbuf[:n]) // Check the key length keylen, err := pk.KeyLength() if err != nil { return nil, err } if MinPublicKeySize < absoluteMinPublicKeySize { panic("MinPublicKeySize has been set less than the allowed absoluteMinPublicKeySize of 2048") } if keylen < MinPublicKeySize { return nil, errors.Wrapf(ErrPubicMinKeySize, "Please use at least %s bits for public-key", MinPublicKeySize) } return pk, nil }
func NewElection(rawElection []byte) (*Election, error) { var ( tagsSec int keySec int signSec int err error electionID string start time.Time end time.Time publicKey PublicKey tagSet TagSet signature Signature ) // Split the election into parts seperated by a double linebreak parts := bytes.Split(rawElection, []byte("\n\n")) // Determine what components exist numParts := len(parts) switch numParts { case 6: tagsSec = 3 keySec = 4 signSec = 5 case 5: // We need to determine if the signature is missing or if the tagset is missing // We do this by looking at the 4th element (index 3) and checking to see if it's a tagset or the public key if bytes.Contains(parts[3], []byte{'\n'}) { // If it contains a linebreak, it's a tagset. The signature is missing. tagsSec = 3 keySec = 4 } else { // It's a public-key. There is a signature but no tagset. keySec = 3 signSec = 4 } case 4: keySec = 3 default: return &Election{}, ErrEelectionInvalid } electionID = string(parts[0]) if len(electionID) > MaxElectionIDSize { return &Election{}, ErrElectionIDTooBig } if !ValidElectionID.MatchString(electionID) { return &Election{}, ErrElectionIDInvalid } start, err = time.Parse(time.RFC1123Z, string(parts[1])) if err != nil { return &Election{}, errors.Wrap(err, ErrElectionStartInvalid) } end, err = time.Parse(time.RFC1123Z, string(parts[2])) if err != nil { return &Election{}, errors.Wrap(err, ErrElectionEndInvalid) } if tagsSec != 0 { tagSet, err = NewTagSet(parts[tagsSec]) if err != nil { return &Election{}, errors.Wrap(err, ErrElectionInvalidTagSet) } } else { tagSet = nil } publicKey, err = NewPublicKey(parts[keySec]) if err != nil { return &Election{}, errors.Wrap(err, ErrElectionInvalidKey) } if signSec != 0 { signature, err = NewSignature(parts[signSec]) if err != nil { return &Election{}, errors.Wrap(err, ErrElectionInvalidSig) } } else { signature = nil } // All checks pass, create and return the election election := Election{ electionID, start, end, tagSet, publicKey, signature, } return &election, nil }
func FooWrappingStdError() error { return errors.Wrap(ErrStd, ErrFoo) }
// Given a raw Signature Request string (as a []byte -- see documentation for format), return a new SignatureRequest object. // Generally the Signature Request string is coming from a voter in a POST body. // This will also verify the signature on the SignatureRequest and return an error if the request does not pass crypto verification func NewSignatureRequest(rawSignatureRequest []byte) (*SignatureRequest, error) { var ( err error hasSign bool electionID string requestID []byte publicKey PublicKey ballotHash []byte signature Signature ) // The SignatureRequest is composed of individual components seperated by double linebreaks parts := bytes.Split(rawSignatureRequest, []byte("\n\n")) numParts := len(parts) switch { case numParts == 4: hasSign = false case numParts == 5: hasSign = true default: return &SignatureRequest{}, ErrSignatureRequestInvalid } electionID = string(parts[0]) publicKey, err = NewPublicKey(parts[2]) if err != nil { return &SignatureRequest{}, errors.Wrap(err, ErrSignatureRequestPublicKey) } requestID = parts[1] if !bytes.Equal(requestID, publicKey.GetSHA256()) { return &SignatureRequest{}, ErrSignatureRequestID } ballotHash = parts[3] n, err := hex.Decode(make([]byte, hex.DecodedLen(len(ballotHash))), ballotHash) if err != nil { return &SignatureRequest{}, ErrSignatureRequestBallotHash } if n != sha256.Size { return &SignatureRequest{}, ErrSignatureRequestHashBits } if hasSign { signature, err = NewSignature(parts[4]) if err != nil { return &SignatureRequest{}, errors.Wrap(err, ErrSignatureRequestSigInvalid) } } else { signature = nil } sigReq := SignatureRequest{ electionID, requestID, publicKey, ballotHash, signature, } // All checks pass return &sigReq, nil }
func StdErrorWrappingFoo() error { return errors.Wrap(ErrFoo, ErrStd) // should panic }
func main() { err1 := errors.Wrap(Err1, Err2) err2 := errors.Append(Err2, Err1) fmt.Printf("%T: %v\n", err1, err1) fmt.Printf("%T: %v\n", err2, err2) }
func FooWrappingBar() error { return errors.Wrap(ErrBar, ErrFoo) }
// Given a raw ballot-string (as a []byte) (see documentation for format), return a new Ballot. // Generally the ballot-string is coming from a client in a PUT body. // This will also verify the signature on the ballot and return an error if the ballot does not pass crypto verification func NewBallot(rawBallot []byte) (*Ballot, error) { var ( tagsSec int signSec int err error electionID string ballotID string vote Vote tagSet TagSet signature Signature ) // Check it's size if len(rawBallot) > MaxBallotSize { return nil, ErrBallotTooBig } // Split the ballot into parts seperated by a double linebreak parts := bytes.Split(rawBallot, []byte("\n\n")) // Determine what components exist numParts := len(parts) switch numParts { case 3: tagsSec = 0 signSec = 0 case 4: // We need to determine if the last element in the ballot is a tag or a signature if bytes.Contains(parts[3], []byte{'\n'}) { // If it contains a linebreak, it's a tagset tagsSec = 3 signSec = 0 } else { // We need to test by looking at length. The maximum tagset size is smaller than the smallest signature if len(parts[3]) > (MaxTagKeySize + MaxTagValueSize + 1) { tagsSec = 0 signSec = 3 } else { tagsSec = 3 signSec = 0 } } case 5: tagsSec = 3 signSec = 4 default: return &Ballot{}, ErrBallotInvalid } electionID = string(parts[0]) if len(electionID) > MaxElectionIDSize { return &Ballot{}, ErrElectionIDTooBig } if !ValidElectionID.MatchString(electionID) { return &Ballot{}, ErrElectionIDInvalid } ballotID = string(parts[1]) if len(ballotID) > MaxBallotIDSize { return &Ballot{}, ErrBallotIDTooBig } if !ValidBallotID.MatchString(ballotID) { return &Ballot{}, ErrBallotIDInvalid } vote, err = NewVote(parts[2]) if err != nil { return &Ballot{}, errors.Wrap(err, ErrBallotInvalidVote) } if tagsSec != 0 { tagSet, err = NewTagSet(parts[tagsSec]) if err != nil { return &Ballot{}, errors.Wrap(err, ErrBallotInvalidTagSet) } } else { tagSet = nil } if signSec != 0 { signature, err = NewSignature(parts[signSec]) if err != nil { return &Ballot{}, errors.Wrap(err, ErrBallotInvalidSig) } } else { signature = nil } // All checks pass, create and return the ballot ballot := Ballot{ electionID, ballotID, vote, tagSet, signature, } return &ballot, nil }