package main import ( "crypto/hmac" cryptoRand "crypto/rand" "crypto/sha1" "crypto/sha256" mathRand "math/rand" "strings" ) func getSHA1Digest(data []byte) []byte { array := sha1.Sum(data) return array[:] } func getSHA2Digest(data []byte) []byte { array := sha256.Sum256(data) return array[:] } func HKDF(data []byte) []byte { h := hmac.New(sha1.New, []byte(strings.Repeat("\x00", 64))) h.Write(data) h1 := h.Sum(nil) h2 := make([]byte, 0) res := make([]byte, 0) for i := 0; i < 2; i++ { h = hmac.New(sha1.New, h1) h.Write(h2) h.Write([]byte{byte(i) + 1}) h2 = h.Sum(nil) res = append(res, h2...) } return res[:0x24] } func genStreamKeys(server bool, data []byte) (sendAESKey, sendHMACKey, receiveAESKey, receiveHMACKey []byte) { const magic2 = "On the client side, this is the send key; on the server side, it is the receive key." const magic3 = "On the client side, this is the receive key; on the server side, it is the send key." var txEnc, rxEnc []byte txEnc = append(data, []byte(strings.Repeat("\x00", 40))...) rxEnc = append(data, []byte(strings.Repeat("\x00", 40))...) if server { txEnc = append(txEnc, magic3...) rxEnc = append(rxEnc, magic2...) } else { txEnc = append(txEnc, magic2...) rxEnc = append(rxEnc, magic3...) } txEnc = append(txEnc, []byte(strings.Repeat("\xF2", 40))...) rxEnc = append(rxEnc, []byte(strings.Repeat("\xF2", 40))...) txEnc = getSHA1Digest(txEnc)[:16] rxEnc = getSHA1Digest(rxEnc)[:16] sendKey := HKDF(txEnc) sendAESKey = sendKey[:16] sendHMACKey = sendKey[16:] receiveKey := HKDF(rxEnc) receiveAESKey = receiveKey[:16] receiveHMACKey = receiveKey[16:] return sendAESKey, sendHMACKey, receiveAESKey, receiveHMACKey } func genPasswordValidatorPriv(username, password string, salt []byte) []byte { if len(salt) != 16 { panic("salt must be 16 bytes") } hash := getSHA2Digest([]byte(username + ":" + password)) return getSHA2Digest(append(salt, hash...)) } func genRandomBytes(n int) ([]byte, error) { b := make([]byte, n) var err error if CfgGetSwitch("crypt-predictable-rng") { _, err = mathRand.Read(b) } else { _, err = cryptoRand.Read(b) } if err != nil { return nil, err } return b, nil } func init() { CfgRegisterSwitch("crypt-predictable-rng", "disable secure rng and use a pseudorandom preseeded rng") mathRand.Seed(300) }