func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { var buffer []byte if version == VersionSSL30 || version >= VersionTLS12 { buffer = []byte{} } prf, hash := prfAndHashForVersion(version, cipherSuite) if hash != 0 { return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} } return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} }
// Sign generates a sign based on the Algorithm instance variable. // This fulfills the `Signer` interface func (s RsaSign) PayloadSign(payload []byte) ([]byte, error) { hash, err := rsaHashForAlg(s.SignatureAlgorithm()) if err != nil { return nil, ErrUnsupportedAlgorithm } privkey := s.PrivateKey if privkey == nil { return nil, ErrMissingPrivateKey } h := hash.New() h.Write(payload) switch s.SignatureAlgorithm() { case jwa.RS256, jwa.RS384, jwa.RS512: return rsa.SignPKCS1v15(rand.Reader, privkey, hash, h.Sum(nil)) case jwa.PS256, jwa.PS384, jwa.PS512: return rsa.SignPSS(rand.Reader, privkey, hash, h.Sum(nil), &rsa.PSSOptions{ SaltLength: rsa.PSSSaltLengthAuto, }) default: return nil, ErrUnsupportedAlgorithm } }
// Parse reads a binary specification for a string-to-key transformation from r // and returns a function which performs that transform. func Parse(r io.Reader) (f func(out, in []byte), err error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) if err != nil { return } // GNU Extensions; handle them before we try to look for a hash, which won't // be needed in most cases anyway. if buf[0] == 101 { return parseGNUExtensions(r) } hash, ok := HashIdToHash(buf[1]) if !ok { return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) } if !hash.Available() { return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) } h := hash.New() switch buf[0] { case 0: f := func(out, in []byte) { Simple(out, h, in) } return f, nil case 1: _, err = io.ReadFull(r, buf[:8]) if err != nil { return } f := func(out, in []byte) { Salted(out, h, in, buf[:8]) } return f, nil case 3: _, err = io.ReadFull(r, buf[:9]) if err != nil { return } count := decodeCount(buf[8]) f := func(out, in []byte) { Iterated(out, h, in, buf[:8], count) } return f, nil } return nil, errors.UnsupportedError("S2K function") }
// Parse reads a binary specification for a string-to-key transformation from r // and returns a function which performs that transform. func Parse(r io.Reader) (f func(out, in []byte), err error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) if err != nil { return } hash, ok := HashIdToHash(buf[1]) if !ok { return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) } if !hash.Available() { return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) } h := hash.New() switch buf[0] { case 0: f := func(out, in []byte) { Simple(out, h, in) } return f, nil case 1: _, err = io.ReadFull(r, buf[:8]) if err != nil { return } f := func(out, in []byte) { Salted(out, h, in, buf[:8]) } return f, nil case 3: _, err = io.ReadFull(r, buf[:9]) if err != nil { return } count := decodeCount(buf[8]) f := func(out, in []byte) { Iterated(out, h, in, buf[:8], count) } return f, nil } return nil, errors.UnsupportedError("S2K function") }
// Parse reads a binary specification for a string-to-key transformation from r // and returns a function which performs that transform. func Parse(r io.Reader) (f func(out, in []byte), err os.Error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) if err != nil { return } hash, ok := HashIdToHash(buf[1]) if !ok { return nil, error.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) } h := hash.New() if h == nil { return nil, error.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) } switch buf[0] { case 1: f := func(out, in []byte) { Simple(out, h, in) } return f, nil case 2: _, err := io.ReadFull(r, buf[:8]) if err != nil { return } f := func(out, in []byte) { Salted(out, h, in, buf[:8]) } return f, nil case 3: _, err := io.ReadFull(r, buf[:9]) if err != nil { return } count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6) f := func(out, in []byte) { Iterated(out, h, in, buf[:8], count) } return f, nil } return nil, error.UnsupportedError("S2K function") }
// PayloadSign generates a sign based on the Algorithm instance variable. // This fulfills the `PayloadSigner` interface func (s EcdsaSign) PayloadSign(payload []byte) ([]byte, error) { hash, err := ecdsaHashForAlg(s.SignatureAlgorithm()) if err != nil { return nil, err } privkey := s.PrivateKey if privkey == nil { return nil, errors.New("cannot proceed with Sign(): no private key available") } keysiz := hash.Size() curveBits := privkey.Curve.Params().BitSize if curveBits != keysiz*8 { return nil, errors.New("key size does not match curve bit size") } h := hash.New() h.Write(payload) signed := h.Sum(nil) if debug.Enabled { debug.Printf("payload = %s, signed -> %x", payload, signed) } r, v, err := ecdsa.Sign(rand.Reader, privkey, signed) if err != nil { return nil, err } out := make([]byte, keysiz*2) keys := [][]byte{r.Bytes(), v.Bytes()} for i, data := range keys { start := i * keysiz padlen := keysiz - len(data) copy(out[start+padlen:], data) } return out, nil }
// Encrypt encrypts a message to a number of recipients and, optionally, signs // it. hints contains optional information, that is also encrypted, that aids // the recipients in processing the message. The resulting WriteCloser must // be closed after the contents of the file have been written. func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints) (plaintext io.WriteCloser, err error) { var signer *packet.PrivateKey if signed != nil { signer = signed.signingKey().PrivateKey if signer == nil || signer.Encrypted { return nil, error_.InvalidArgumentError("signing key must be decrypted") } } // These are the possible ciphers that we'll use for the message. candidateCiphers := []uint8{ uint8(packet.CipherAES128), uint8(packet.CipherAES256), uint8(packet.CipherCAST5), } // These are the possible hash functions that we'll use for the signature. candidateHashes := []uint8{ hashToHashId(crypto.SHA256), hashToHashId(crypto.SHA512), hashToHashId(crypto.SHA1), hashToHashId(crypto.RIPEMD160), } // In the event that a recipient doesn't specify any supported ciphers // or hash functions, these are the ones that we assume that every // implementation supports. defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] defaultHashes := candidateHashes[len(candidateHashes)-1:] encryptKeys := make([]Key, len(to)) for i := range to { encryptKeys[i] = to[i].encryptionKey() if encryptKeys[i].PublicKey == nil { return nil, error_.InvalidArgumentError("cannot encrypt a message to key id " + strconv.Uitob64(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") } sig := to[i].primaryIdentity().SelfSignature preferredSymmetric := sig.PreferredSymmetric if len(preferredSymmetric) == 0 { preferredSymmetric = defaultCiphers } preferredHashes := sig.PreferredHash if len(preferredHashes) == 0 { preferredHashes = defaultHashes } candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) candidateHashes = intersectPreferences(candidateHashes, preferredHashes) } if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { return nil, error_.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") } cipher := packet.CipherFunction(candidateCiphers[0]) hash, _ := s2k.HashIdToHash(candidateHashes[0]) symKey := make([]byte, cipher.KeySize()) if _, err := io.ReadFull(rand.Reader, symKey); err != nil { return nil, err } for _, key := range encryptKeys { if err := packet.SerializeEncryptedKey(ciphertext, rand.Reader, key.PublicKey, cipher, symKey); err != nil { return nil, err } } encryptedData, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey) if err != nil { return } if signer != nil { ops := &packet.OnePassSignature{ SigType: packet.SigTypeBinary, Hash: hash, PubKeyAlgo: signer.PubKeyAlgo, KeyId: signer.KeyId, IsLast: true, } if err := ops.Serialize(encryptedData); err != nil { return nil, err } } if hints == nil { hints = &FileHints{} } w := encryptedData if signer != nil { // If we need to write a signature packet after the literal // data then we need to stop literalData from closing // encryptedData. w = noOpCloser{encryptedData} } literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, hints.EpochSeconds) if err != nil { return nil, err } if signer != nil { return signatureWriter{encryptedData, literalData, hash, hash.New(), signer}, nil } return literalData, nil }
// Parse reads a binary specification for a string-to-key transformation from r // and returns a function which performs that transform. func Parse(r io.Reader) (f func(out, in []byte), err error) { var buf [9]byte _, err = io.ReadFull(r, buf[:2]) if err != nil { return } hash, ok := HashIdToHash(buf[1]) if !ok { return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) } if !hash.Available() { return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) } h := hash.New() switch buf[0] { case 0: f := func(out, in []byte) { Simple(out, h, in) } return f, nil case 1: _, err = io.ReadFull(r, buf[:8]) if err != nil { return } f := func(out, in []byte) { Salted(out, h, in, buf[:8]) } return f, nil case 3: _, err = io.ReadFull(r, buf[:9]) if err != nil { return } count := decodeCount(buf[8]) f := func(out, in []byte) { Iterated(out, h, in, buf[:8], count) } return f, nil // GNU Extensions case 101: // A three-byte string identifier _, err = io.ReadFull(r, buf[:3]) if err != nil { return } gnuExt := string(buf[:3]) if gnuExt != "GNU" { return nil, errors.UnsupportedError("Malformed GNU extension: " + gnuExt) } _, err = io.ReadFull(r, buf[:1]) if err != nil { return } gnuExtType := int(buf[0]) if gnuExtType != 1 { return nil, errors.UnsupportedError("unknown S2K GNU protection mode: " + strconv.Itoa(int(gnuExtType))) } return nil, nil } return nil, errors.UnsupportedError("S2K function") }