func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { hashLen = hash.Size() if inLen != hashLen { return 0, nil, errors.New("input must be hashed message") } prefix, ok := hashPrefixes[hash] if !ok { return 0, nil, errors.New("unsupported hash function") } return }
// EncodeDigest encodes a hash algorithm and a digest to be put in an assertion header. func EncodeDigest(hash crypto.Hash, hashDigest []byte) (string, error) { algo := "" switch hash { case crypto.SHA256: algo = "sha256" default: return "", fmt.Errorf("unsupported hash") } if len(hashDigest) != hash.Size() { return "", fmt.Errorf("hash digest by %s should be %d bytes", algo, hash.Size()) } return fmt.Sprintf("%s %s", algo, base64.RawURLEncoding.EncodeToString(hashDigest)), nil }
// SignPSS calculates the signature of hashed using RSASSA-PSS [1]. // Note that hashed must be the result of hashing the input message using the // given hash funcion. The opts argument may be nil, in which case sensible // defaults are used. func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) (s []byte, err error) { saltLength := opts.saltLength() switch saltLength { case PSSSaltLengthAuto: saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size() case PSSSaltLengthEqualsHash: saltLength = hash.Size() } salt := make([]byte, saltLength) if _, err = io.ReadFull(rand, salt); err != nil { return } return signPSSWithSalt(rand, priv, hash, hashed, salt) }
func checkDigest(headers map[string]interface{}, name string, h crypto.Hash) ([]byte, error) { digestStr, err := checkNotEmptyString(headers, name) if err != nil { return nil, err } b, err := base64.RawURLEncoding.DecodeString(digestStr) if err != nil { return nil, fmt.Errorf("%q header cannot be decoded: %v", name, err) } if len(b) != h.Size() { return nil, fmt.Errorf("%q header does not have the expected bit length: %d", name, len(b)*8) } return b, nil }
func (h Hash) Validate() report.Report { var hash crypto.Hash switch h.Function { case "sha512": hash = crypto.SHA512 default: return report.ReportFromError(ErrHashUnrecognized, report.EntryError) } if len(h.Sum) != hex.EncodedLen(hash.Size()) { return report.ReportFromError(ErrHashWrongSize, report.EntryError) } return report.Report{} }
func (h Hash) AssertValid() error { var hash crypto.Hash switch h.Function { case "sha512": hash = crypto.SHA512 default: return ErrHashUnrecognized } if len(h.Sum) != hex.EncodedLen(hash.Size()) { return ErrHashWrongSize } return nil }
func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { // Special case: crypto.Hash(0) is used to indicate that the data is // signed directly. if hash == 0 { return inLen, nil, nil } hashLen = hash.Size() if inLen != hashLen { return 0, nil, errors.New("crypto/rsa: input must be hashed message") } prefix, ok := hashPrefixes[hash] if !ok { return 0, nil, errors.New("crypto/rsa: unsupported hash function") } return }
func ssl30MAC(hash crypto.Hash, key, input, ad []byte) []byte { padLength := 48 if hash.Size() == 20 { padLength = 40 } h := hash.New() h.Write(key) h.Write(ssl30Pad1[:padLength]) h.Write(ad) h.Write(input) digestBuf := h.Sum(nil) h.Reset() h.Write(key) h.Write(ssl30Pad2[:padLength]) h.Write(digestBuf) return h.Sum(digestBuf[:0]) }
// This function creates a new TOTP object // This is the function which is needed to start the whole process // account: usually the user email // issuer: the name of the company/service // hash: is the crypto function used: crypto.SHA1, crypto.SHA256, crypto.SHA512 // digits: is the token amount of digits (6 or 7 or 8) // steps: the amount of second the token is valid // it autmatically generates a secret key using the golang crypto rand package. If there is not enough entropy the function returns an error // The key is not encrypted in this package. It's a secret key. Therefore if you transfer the key bytes in the network, // please take care of protecting the key or in fact all the bytes. func NewTOTP(account, issuer string, hash crypto.Hash, digits int) (*Totp, error) { keySize := hash.Size() key := make([]byte, keySize) total, err := rand.Read(key) if err != nil { return nil, errors.New(fmt.Sprintf("TOTP failed to create because there is not enough entropy, we got only %d random bytes", total)) } // sanitize the digits range otherwise it may create invalid tokens ! if digits < 6 || digits > 8 { digits = 8 } return makeTOTP(key, account, issuer, hash, digits) }
// verifyPSS verifies a PSS signature with the given salt length. func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error { nBits := pub.N.BitLen() if len(sig) != (nBits+7)/8 { return ErrVerification } s := new(big.Int).SetBytes(sig) m := encrypt(new(big.Int), pub, s) emBits := nBits - 1 emLen := (emBits + 7) / 8 if emLen < len(m.Bytes()) { return ErrVerification } em := make([]byte, emLen) copyWithLeftPad(em, m.Bytes()) if saltLen == PSSSaltLengthEqualsHash { saltLen = hash.Size() } return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New()) }