func (hashStruct *Pbkdf2Hash) UnmarshalJSON(input []byte) error { var t struct { Hash string Salt string Iterations uint16 } dec := json.NewDecoder(bytes.NewReader(input)) if e := dec.Decode(&t); e != nil { return e } else if h, e := base64.StdEncoding.DecodeString(t.Hash); e != nil { return e } else if len(h) != Pbkdf2KeyLength { return IncorrectHashLengthError } else if s, e := base64.StdEncoding.DecodeString(t.Salt); e != nil { return e } else if len(s) != Pbkdf2KeyLength { return IncorrectSaltLengthError } else if t.Iterations < Pbkdf2MinIterations { return InsufficientIterationsError } else { subtle.ConstantTimeCopy(1, hashStruct.Hash[:], h) subtle.ConstantTimeCopy(1, hashStruct.Salt[:], s) hashStruct.Iterations = t.Iterations return nil } }
func (s *Server) AuthHandler() http.Handler { handler := func(w http.ResponseWriter, r *http.Request) { /* Parse form data and handle error messages. Might not be the most visible to the end user. */ err := r.ParseForm() if err != nil { fmt.Println(err) return } message := r.FormValue("message") signature := r.FormValue("signature") publicKey := r.FormValue("publicKey") /* Decode publicKey and signature to a byte array using base64url package */ pubBytes, pubErr := base64url.Decode(publicKey) if pubErr != nil { fmt.Println(pubErr) } signBytes, signErr := base64url.Decode(signature) if signErr != nil { fmt.Println(signErr) } /* Change the byte array to an object with the correct sizes used by the ed25519 implementation */ var pk *[ed25519.PublicKeySize]byte pk = new([ed25519.PublicKeySize]byte) subtle.ConstantTimeCopy(1, pk[:32], pubBytes) var sig *[ed25519.SignatureSize]byte sig = new([ed25519.SignatureSize]byte) subtle.ConstantTimeCopy(1, sig[:64], signBytes) /* Verify the signature and return verified or not depending on the result. */ w.Header().Add("Content-Type", "text/html") if ed25519.Verify(pk, []byte(message), sig) { io.WriteString(w, "{result:true}Verified") } else { io.WriteString(w, "{result:false}Not Verified") } } return http.HandlerFunc(handler) }
// SetPassword is a function that allows a password to be hashed and added to // an InMemPwdStore instance. func GetPbkdf2Hash( password string, iterations uint16, ) (*Pbkdf2Hash, error) { if iterations < Pbkdf2MinIterations { return nil, InsufficientIterationsError } var hashStruct Pbkdf2Hash randCount, err := rand.Read(hashStruct.Salt[:]) if err != nil { return nil, err } else if randCount != Pbkdf2KeyLength { return nil, InsufficientEntropyError } hashStruct.Iterations = iterations subtle.ConstantTimeCopy(1, hashStruct.Hash[:], pbkdf2.Key( []byte(password), hashStruct.Salt[:], int(hashStruct.Iterations), Pbkdf2KeyLength, sha256.New, )) return &hashStruct, nil }
// 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") } }
// 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 }
// Verify returns true if the cryptographic signature sig. func (k *Key) Verify(msg []byte, sig *Signature) bool { var pk *[ed25519.PublicKeySize]byte subtle.ConstantTimeCopy(1, pk[:32], k[:]) // pk := [ed25519.PublicKeySize]byte(*k) s := [ed25519.SignatureSize]byte(*sig) return ed25519.Verify(pk, msg, &s) }
// DomainKey returns the private key for domain. // HMAC-SHA256 using k as the key and domain as the message to generate the 256-bit private key. func (k *Key) DomainKey(domain string) (key *Key) { mac := hmac.New(sha256.New, k[:]) mac.Write([]byte(domain)) bytes := mac.Sum(nil) subtle.ConstantTimeCopy(1, key[:keyLen], bytes[:keyLen]) return }
//TODO test MakePassword func MakePassword(pass []byte) []byte { salt := make([]byte, SaltSize) _, err := rand.Read(salt) if err != nil { return nil } key := HashPassword(pass, salt) if key == nil { return nil } hashed := make([]byte, KeySize+SaltSize) subtle.ConstantTimeCopy(1, hashed[:SaltSize], salt) subtle.ConstantTimeCopy(1, hashed[SaltSize:], key) return hashed }
func DeriveKey(password, salt []byte, N, r, p, n int) (key *Key, err error) { // Derive key using password and salt. k, err := scrypt.Key(password, salt, N, r, p, n) if err != nil { return } subtle.ConstantTimeCopy(1, key[:], k) return }
// ChangePassword func (this *Identity) ChangePassword(old, new string) (ok bool, err error) { // Recover master key. master, err := this.recoverMasterKey(old) if err != nil { return } salt := cryptoRand(saltLen) key, err := DeriveKey([]byte(new), salt, this.N, this.R, this.P, keyLen) if err != nil { return } key.Xor(master) subtle.ConstantTimeCopy(1, this.Key[:keyLen], key[:keyLen]) subtle.ConstantTimeCopy(1, this.Check[:16], key.Hash()[:16]) subtle.ConstantTimeCopy(1, this.Salt[:8], salt[:8]) return }
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)) }
// 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 }
// 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 }
// decrypt an elgamal encrypted message, i2p style func elgamalDecrypt(priv *elgamal.PrivateKey, data []byte, zeroPadding bool) (decrypted []byte, err error) { a := new(big.Int) b := new(big.Int) idx := 0 if zeroPadding { idx++ } a.SetBytes(data[idx : idx+256]) if zeroPadding { idx++ } b.SetBytes(data[idx+256:]) // decrypt m := new(big.Int).Mod(new(big.Int).Mul(b, new(big.Int).Exp(a, new(big.Int).Sub(new(big.Int).Sub(priv.P, priv.X), one), priv.P)), priv.P).Bytes() // check digest d := sha256.Sum256(m[33:255]) good := 0 if subtle.ConstantTimeCompare(d[:], m[1:33]) == 1 { // decryption successful good = 1 } else { // decrypt failed err = ElgDecryptFail } // copy result decrypted = make([]byte, 222) subtle.ConstantTimeCopy(good, decrypted, m[33:255]) if good == 0 { // if decrypt failed nil out decrypted slice decrypted = nil } return }
func constantTimeCopy(v int, x, y []byte) { subtle.ConstantTimeCopy(v, x, y) }
// Sign returns the cryptographic signature of the []byte msg. func (k *Key) Sign(msg []byte) (sig *Signature) { var pk *[ed25519.PrivateKeySize]byte subtle.ConstantTimeCopy(1, pk[:32], k[:]) s := Signature(*ed25519.Sign(pk, msg)) return &s }
// PublicKey returns the corresponding public key. func (k *Key) PublicKey() *Key { var pk *[ed25519.PrivateKeySize]byte subtle.ConstantTimeCopy(1, pk[:32], k[:]) key := Key(*ed25519.GeneratePublicKey(pk)) return &key }