// Decrypt implements the crypto.Decrypter operation for the given key. func (key *PrivateKey) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) ([]byte, error) { switch opts := opts.(type) { case *rsa.PKCS1v15DecryptOptions: ptxt, decyptErr := key.execute(gokeyless.OpRSADecrypt, msg) // If opts.SessionKeyLen is set, we must perform a variation of // rsa.DecryptPKCS1v15SessionKey to ensure the entire operation // is performed in constant time regardless of padding errors. if l := opts.SessionKeyLen; l > 0 { plaintext := make([]byte, l) if _, err := io.ReadFull(rand, plaintext); err != nil { return nil, err } valid := subtle.ConstantTimeEq(int32(len(ptxt)), int32(l)) v2 := subtle.ConstantTimeLessOrEq(l, len(ptxt)) l2 := subtle.ConstantTimeSelect(v2, l, len(ptxt)) subtle.ConstantTimeCopy(valid, plaintext[:l2], ptxt[:l2]) return plaintext, nil } // Otherwise, we can just return the error like rsa.DecryptPKCS1v15. return ptxt, decyptErr default: return nil, errors.New("invalid options for Decrypt") } }
func secureCompare(given, actual string) bool { if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { return subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 } /* Securely compare actual to itself to keep constant time, but always return false */ return subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 && false }
// Decrypt implements the crypto.Decrypter operation for the given key. func (key *PrivateKey) Decrypt(rand io.Reader, msg []byte, opts crypto.DecrypterOpts) ([]byte, error) { opts1v15, ok := opts.(*rsa.PKCS1v15DecryptOptions) if opts != nil && !ok { return nil, errors.New("invalid options for Decrypt") } ptxt, err := key.execute(gokeyless.OpRSADecrypt, msg) if err != nil { return nil, err } if ok { // If opts.SessionKeyLen is set, we must perform a variation of // rsa.DecryptPKCS1v15SessionKey to ensure the entire operation // is performed in constant time regardless of padding errors. if l := opts1v15.SessionKeyLen; l > 0 { plaintext := make([]byte, l) if _, err := io.ReadFull(rand, plaintext); err != nil { return nil, err } valid := subtle.ConstantTimeEq(int32(len(ptxt)), int32(l)) v2 := subtle.ConstantTimeLessOrEq(l, len(ptxt)) l2 := subtle.ConstantTimeSelect(v2, l, len(ptxt)) subtle.ConstantTimeCopy(valid, plaintext[:l2], ptxt[:l2]) return plaintext, nil } } return ptxt, nil }
func main() { log.Printf("%d", subtle.ConstantTimeByteEq(43, 65)) log.Printf("%d", subtle.ConstantTimeCompare([]byte("batman"), []byte("robin "))) bytes := make([]byte, 6) subtle.ConstantTimeCopy(1, bytes, []byte("batman")) log.Printf("%s", bytes) log.Printf("%d", subtle.ConstantTimeEq(256, 255)) log.Printf("%d", subtle.ConstantTimeSelect(1, 2, 3)) log.Printf("%d", subtle.ConstantTimeSelect(0, 2, 3)) }
func SecureCompare(given, actual []byte) bool { if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { if subtle.ConstantTimeCompare(given, actual) == 1 { return true } return false } // Securely compare actual to itself to keep constant time, but always return false if subtle.ConstantTimeCompare(actual, actual) == 1 { return false } return false }
// Authenticate check the user credentials. func Authenticate(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { if subtle.ConstantTimeEq(int32(len(r.FormValue("password"))), int32(len(configuration.Password))) == 0 { http.Redirect(w, r, "/login", http.StatusFound) return } if subtle.ConstantTimeCompare([]byte(r.FormValue("password")), []byte(configuration.Password)) == 0 { http.Redirect(w, r, "/login", http.StatusFound) return } sessions.GetSession(r).Set("logged", true) http.Redirect(w, r, "/read", http.StatusFound) }
// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5. // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. // It returns an error if the ciphertext is the wrong length or if the // ciphertext is greater than the public modulus. Otherwise, no error is // returned. If the padding is valid, the resulting plaintext message is copied // into key. Otherwise, key is unchanged. These alternatives occur in constant // time. It is intended that the user of this function generate a random // session key beforehand and continue the protocol with the resulting value. // This will remove any possibility that an attacker can learn any information // about the plaintext. // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology // (Crypto '98), func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) { k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { err = DecryptionError{} return } valid, msg, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { return } valid &= subtle.ConstantTimeEq(int32(len(msg)), int32(len(key))) subtle.ConstantTimeCopy(valid, key, msg) return }
func SecureCompareString(given, actual string) bool { // The following code is incorrect: // return SecureCompare([]byte(given), []byte(actual)) if subtle.ConstantTimeEq(int32(len(given)), int32(len(actual))) == 1 { if subtle.ConstantTimeCompare([]byte(given), []byte(actual)) == 1 { return true } return false } // Securely compare actual to itself to keep constant time, but always return false if subtle.ConstantTimeCompare([]byte(actual), []byte(actual)) == 1 { return false } return false }
// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5. // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. // It returns an error if the ciphertext is the wrong length or if the // ciphertext is greater than the public modulus. Otherwise, no error is // returned. If the padding is valid, the resulting plaintext message is copied // into key. Otherwise, key is unchanged. These alternatives occur in constant // time. It is intended that the user of this function generate a random // session key beforehand and continue the protocol with the resulting value. // This will remove any possibility that an attacker can learn any information // about the plaintext. // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology // (Crypto '98). func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) { if err := checkPub(&priv.PublicKey); err != nil { return err } k := (priv.N.BitLen() + 7) / 8 if k-(len(key)+3+8) < 0 { return ErrDecryption } valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) if err != nil { return } if len(em) != k { // This should be impossible because decryptPKCS1v15 always // returns the full slice. return ErrDecryption } valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) return }
// IsKeySuitable returns true if the byte slice represents a valid // secretbox key. func KeyIsSuitable(key []byte) bool { return subtle.ConstantTimeEq(int32(len(key)), int32(KeySize)) == 1 }