func main() { plainText := []byte("Bob loves Alice. But Alice hate Bob...") key := []byte("passw0rdpassw0rdpassw0rdpassw0rd") // Create new AES cipher block block, err := aes.NewCipher(key) if err != nil { fmt.Printf("err: %s\n", err) } // The IV (Initialization Vector) need to be unique, but not secure. // Therefore, it's common to include it at the beginning of the cipher text. cipherText := make([]byte, aes.BlockSize+len(plainText)) // Create IV iv := cipherText[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { fmt.Printf("err: %s\n", err) } // Encrypt encryptStream := cipher.NewCTR(block, iv) encryptStream.XORKeyStream(cipherText[aes.BlockSize:], plainText) fmt.Printf("Cipher text: %x \n", cipherText) // Decrpt decryptedText := make([]byte, len(cipherText[aes.BlockSize:])) decryptStream := cipher.NewCTR(block, cipherText[:aes.BlockSize]) decryptStream.XORKeyStream(decryptedText, cipherText[aes.BlockSize:]) fmt.Printf("Decrypted text: %s\n", string(decryptedText)) }
func TestCTR_AES(t *testing.T) { for _, tt := range ctrAESTests { test := tt.name c, err := aes.NewCipher(tt.key) if err != nil { t.Errorf("%s: NewCipher(%d bytes) = %s", test, len(tt.key), err) continue } for j := 0; j <= 5; j += 5 { in := tt.in[0 : len(tt.in)-j] ctr := cipher.NewCTR(c, tt.iv) encrypted := make([]byte, len(in)) ctr.XORKeyStream(encrypted, in) if out := tt.out[0:len(in)]; !bytes.Equal(out, encrypted) { t.Errorf("%s/%d: CTR\ninpt %x\nhave %x\nwant %x", test, len(in), in, encrypted, out) } } for j := 0; j <= 7; j += 7 { in := tt.out[0 : len(tt.out)-j] ctr := cipher.NewCTR(c, tt.iv) plain := make([]byte, len(in)) ctr.XORKeyStream(plain, in) if out := tt.in[0:len(in)]; !bytes.Equal(out, plain) { t.Errorf("%s/%d: CTRReader\nhave %x\nwant %x", test, len(out), plain, out) } } if t.Failed() { break } } }
func ExampleNewCTR() { key := []byte("example key 1234") plaintext := []byte("some plaintext") block, err := aes.NewCipher(key) if err != nil { panic(err) } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. ciphertext := make([]byte, aes.BlockSize+len(plaintext)) iv := ciphertext[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { panic(err) } stream := cipher.NewCTR(block, iv) stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext) // It's important to remember that ciphertexts must be authenticated // (i.e. by using crypto/hmac) as well as being encrypted in order to // be secure. // CTR mode is the same for both encryption and decryption, so we can // also decrypt that ciphertext with NewCTR. plaintext2 := make([]byte, len(plaintext)) stream = cipher.NewCTR(block, iv) stream.XORKeyStream(plaintext2, ciphertext[aes.BlockSize:]) fmt.Printf("%s\n", plaintext2) // Output: some plaintext }
func (conn *obfs3Conn) kdf(sharedSecret []byte) error { // Using that shared-secret each party derives its encryption keys as // follows: // // INIT_SECRET = HMAC(SHARED_SECRET, "Initiator obfuscated data") // RESP_SECRET = HMAC(SHARED_SECRET, "Responder obfuscated data") // INIT_KEY = INIT_SECRET[:KEYLEN] // INIT_COUNTER = INIT_SECRET[KEYLEN:] // RESP_KEY = RESP_SECRET[:KEYLEN] // RESP_COUNTER = RESP_SECRET[KEYLEN:] initHmac := hmac.New(sha256.New, sharedSecret) initHmac.Write([]byte(initiatorKdfString)) initSecret := initHmac.Sum(nil) initHmac.Reset() initHmac.Write([]byte(initiatorMagicString)) initMagic := initHmac.Sum(nil) respHmac := hmac.New(sha256.New, sharedSecret) respHmac.Write([]byte(responderKdfString)) respSecret := respHmac.Sum(nil) respHmac.Reset() respHmac.Write([]byte(responderMagicString)) respMagic := respHmac.Sum(nil) // The INIT_KEY value keys a block cipher (in CTR mode) used to // encrypt values from initiator to responder thereafter. The counter // mode's initial counter value is INIT_COUNTER. The RESP_KEY value // keys a block cipher (in CTR mode) used to encrypt values from // responder to initiator thereafter. That counter mode's initial // counter value is RESP_COUNTER. // // Note: To have this be the last place where the shared secret is used, // also generate the magic value to send/scan for here. initBlock, err := aes.NewCipher(initSecret[:keyLen]) if err != nil { return err } initStream := cipher.NewCTR(initBlock, initSecret[keyLen:]) respBlock, err := aes.NewCipher(respSecret[:keyLen]) if err != nil { return err } respStream := cipher.NewCTR(respBlock, respSecret[keyLen:]) if conn.isInitiator { conn.tx = &cipher.StreamWriter{S: initStream, W: conn.Conn} conn.rx = &cipher.StreamReader{S: respStream, R: conn.rxBuf} conn.txMagic = initMagic conn.rxMagic = respMagic } else { conn.tx = &cipher.StreamWriter{S: respStream, W: conn.Conn} conn.rx = &cipher.StreamReader{S: initStream, R: conn.rxBuf} conn.txMagic = respMagic conn.rxMagic = initMagic } return nil }
func encrypt_data(plain, keys []byte) ([]byte, error) { var iv, key []byte var block cipher.Block var stream cipher.Stream iv_offset := TotalIVLen res := make([]byte, len(plain)+iv_offset) iv = res[iv_offset-SalsaIVLen : iv_offset] _, err := rand.Read(iv) if err != nil { return nil, err } // For some reason salsa20 API is different key_array := new([32]byte) copy(key_array[:], keys[cipherKeyLen*2:]) salsa20.XORKeyStream(res[iv_offset:], plain, iv, key_array) iv_offset -= SalsaIVLen iv = res[iv_offset-IVLen : iv_offset] _, err = rand.Read(iv) if err != nil { return nil, err } key = keys[cipherKeyLen : cipherKeyLen*2] block, err = twofish.NewCipher(key) if err != nil { return nil, err } stream = cipher.NewCTR(block, iv) stream.XORKeyStream(res[iv_offset:], res[iv_offset:]) iv_offset -= IVLen iv = res[iv_offset-IVLen : iv_offset] _, err = rand.Read(iv) if err != nil { return nil, err } key = keys[:cipherKeyLen] block, err = aes.NewCipher(key) if err != nil { return nil, err } stream = cipher.NewCTR(block, iv) stream.XORKeyStream(res[iv_offset:], res[iv_offset:]) iv_offset -= IVLen if iv_offset != 0 { panic(fmt.Errorf("something went terribly wrong: iv_offset final value non-zero")) } return res, nil }
// decode uses the given block cipher (in CTR mode) to decrypt the // data, and validate the hash. If hash validation fails, an error is // returned. func decode(block cipher.Block, hmac hash.Hash, ciphertext []byte) ([]byte, error) { if len(ciphertext) < 2*block.BlockSize()+hmac.Size() { return nil, LenError } receivedHmac := ciphertext[len(ciphertext)-hmac.Size():] ciphertext = ciphertext[:len(ciphertext)-hmac.Size()] hmac.Write(ciphertext) if subtle.ConstantTimeCompare(hmac.Sum(nil), receivedHmac) != 1 { return nil, HashError } // split the iv and session bytes iv := ciphertext[len(ciphertext)-block.BlockSize():] session := ciphertext[:len(ciphertext)-block.BlockSize()] stream := cipher.NewCTR(block, iv) stream.XORKeyStream(session, session) // skip past the iv session = session[block.BlockSize():] return session, nil }
func streamCipherReaderForKeyData(keyType byte, keyData []byte, r io.ReadCloser) (io.ReadCloser, error) { switch keyType { case keyTypeAES: if len(keyData) != keyTypeAESKeySize { return nil, ErrInvalidKey } // Ignore error below, aes will fail only if the size of key is // invalid. We fully control it and pass valid value. block, _ := aes.NewCipher(keyData) var iv [aes.BlockSize]byte stream := cipher.NewCTR(block, iv[:]) return &streamReader{cipher.StreamReader{S: stream, R: r}}, nil case keyTypeChaCha20: if len(keyData) != chacha20.KeySize { return nil, ErrInvalidKey } var nonce [chacha20.NonceSize]byte // Ignore error below, chacha20 will fail only if the size of key or // nonce are invalid. We fully control those and pass valid values. stream, _ := chacha20.NewCipher(keyData, nonce[:]) return &streamReader{cipher.StreamReader{S: stream, R: r}}, nil default: return nil, ErrInvalidKey } }
func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) { if len(encrypted) < aes.BlockSize+sha256.Size { return nil, false } iv := encrypted[:aes.BlockSize] macBytes := encrypted[len(encrypted)-sha256.Size:] mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32]) mac.Write(encrypted[:len(encrypted)-sha256.Size]) expected := mac.Sum(nil) if subtle.ConstantTimeCompare(macBytes, expected) != 1 { return nil, false } block, err := aes.NewCipher(c.config.SessionTicketKey[:16]) if err != nil { return nil, false } ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] plaintext := make([]byte, len(ciphertext)) cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) state := new(sessionState) ok := state.unmarshal(plaintext) return state, ok }
// encrypt encrypts a value using the given Block in CTR mode. // // A random initialization vector is generated and prepended to the resulting // ciphertext to be available for decryption. Also, a random salt with the // length of the block size is prepended to the value before encryption. func encrypt(block cipher.Block, value []byte) (rv []byte, err error) { // Recover in case block has an invalid key. defer func() { if r := recover(); r != nil { err = r.(error) } }() size := block.BlockSize() // Generate an initialization vector suitable for encryption. // http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Initialization_vector_.28IV.29 iv := make([]byte, size) if _, err = rand.Read(iv); err != nil { return } // Create a salt. salt := make([]byte, size) if _, err = rand.Read(salt); err != nil { return } value = append(salt, value...) // Encrypt it. stream := cipher.NewCTR(block, iv) stream.XORKeyStream(value, value) // Return iv + ciphertext. rv = append(iv, value...) return }
// Unseal reverses the operations in Seal to decrypt the enclosed data, verify its integrity and checks timeliness against time.Now(). The error // result MUST BE CHECKED in all cases, as Unseal will always return what it believes to be the decrypted but not authenticated data. func Unseal(auth, key, seal []byte) ([]byte, error) { if len(seal) < 56 { return seal, SEAL_UNDERFLOW } // We copy off the seal because we're about to manipulate it destructively. seal = append(make([]byte, 0, len(seal)), seal...) hash := hmac.New(sha256.New, auth) // Decrypt our HMAC and PLAINTEXT b, err := aes.NewCipher(key) if err != nil { return nil, err } cipher.NewCTR(b, seal[:16]).XORKeyStream(seal[16:], seal[16:]) // Extract our Timestamp expiry := binary.LittleEndian.Uint64(seal[16:24]) // Compare our HMAC hash.Write(seal[0:24]) hash.Write(seal[56:]) if bytes.Compare(seal[24:56], hash.Sum(nil)) != 0 { return nil, SEAL_MISMATCH } // Compare our expiry if time.Now().After(time.Unix(int64(expiry), 0)) { return nil, SEAL_EXPIRED } return seal[56:], nil }
// Seal uses SHA256 in a HMAC configuration to authenticate data, and then encrypts it using AES-CTR with a random IV. This protects the // sealed data from modification or analysis by the recipient. An expiry time is also sealed into the data structure, limiting the viability // of the seal. func Seal(auth, key, data []byte, exp time.Time) ([]byte, error) { hash := hmac.New(sha256.New, auth) seal := make([]byte, len(data)+56) // Read our IV _, err := rand.Read(seal[:16]) if err != nil { return nil, err } // Apply our Stamp binary.LittleEndian.PutUint64(seal[16:], uint64(exp.Unix())) // Copy in our plaintext. copy(seal[56:], data) // HMAC everything before and after the HMAC field. hash.Write(seal[0:24]) hash.Write(seal[56:]) copy(seal[24:56], hash.Sum(nil)) // Encrypt our HMAC and PLAINTEXT b, err := aes.NewCipher(key) if err != nil { return nil, err } cipher.NewCTR(b, seal[:16]).XORKeyStream(seal[16:], seal[16:]) return seal, nil }
func decryptNym(key, encNym []byte) []byte { block, _ := aes.NewCipher(key) // Keysize is ok, so no error should occur stream := cipher.NewCTR(block, make([]byte, aes.BlockSize)) // This is not very secure, but good enough since key should change a lot stream.XORKeyStream(encNym, encNym) // Decrypt l := int(encNym[0]) return encNym[1 : l+1] // cut nym from cleartext }
// Assembles the crypto primitives needed for a one way communication channel: // the stream cipher for encryption and the mac for authentication. func makeHalfDuplex(hkdf io.Reader) (cipher.Stream, hash.Hash) { // Extract the symmetric key and create the block cipher key := make([]byte, config.SessionCipherBits/8) n, err := io.ReadFull(hkdf, key) if n != len(key) || err != nil { panic(fmt.Sprintf("Failed to extract session key: %v", err)) } block, err := config.SessionCipher(key) if err != nil { panic(fmt.Sprintf("Failed to create session cipher: %v", err)) } // Extract the IV for the counter mode and create the stream cipher iv := make([]byte, block.BlockSize()) n, err = io.ReadFull(hkdf, iv) if n != len(iv) || err != nil { panic(fmt.Sprintf("Failed to extract session IV: %v", err)) } stream := cipher.NewCTR(block, iv) // Extract the HMAC key and create the session MACer salt := make([]byte, config.SessionHash().Size()) n, err = io.ReadFull(hkdf, salt) if n != len(salt) || err != nil { panic(fmt.Sprintf("Failed to extract session mac salt: %v", err)) } mac := hmac.New(config.SessionHash, salt) return stream, mac }
func Decode(key []byte, rvalue string) ([]byte, error) { if len(rvalue) == 0 { return nil, nil } if len(key) == 0 { return []byte(rvalue), nil } // NOTE: using the URLEncoding.Decode(...) seems to muck with the // returned value. Using string, which wants to return a cleaner // version. value, err := base64.URLEncoding.DecodeString(rvalue) if err != nil { return nil, err } block, err := aes.NewCipher(key) if err != nil { return nil, err } blockSize := block.BlockSize() if len(value) < blockSize { return nil, ValueSizeError(len(value)) } iv := value[:blockSize] value = value[blockSize:] stream := cipher.NewCTR(block, iv) stream.XORKeyStream(value, value) return value, nil }
//given a blob of text to decode, checks a few things and returns either //the originally given unique id and true or "" and false. func decryptSessionId(encryptedHex string, block cipher.Block) (string, bool) { ciphertext := make([]byte, len(encryptedHex)/2) l, err := hex.Decode(ciphertext, []byte(encryptedHex)) if err != nil { log.Printf("unable to decode the hex bytes of session id (%s,%d): %v", encryptedHex, len(encryptedHex), err) return "", false } iv := ciphertext[:aes.BlockSize] stream := cipher.NewCTR(block, iv) cleartext := make([]byte, l-len(iv)) stream.XORKeyStream(cleartext, ciphertext[aes.BlockSize:]) s := string(cleartext) if !strings.HasPrefix(s, s5CookiePrefix) { log.Printf("No cookie prefix found, probably keys changed") return "", false } s = strings.TrimPrefix(s, s5CookiePrefix+":") parts := strings.Split(s, ",") if len(parts) != 2 { log.Printf("Failed to understand parts of session id: %s", s) return "", false } t, err := strconv.ParseInt(parts[1], 10, 64) if err != nil { log.Printf("Could not understand expiration time in session id: %s", s) return "", false } expires := time.Unix(t, 0) if expires.Before(time.Now()) { return "", false } return parts[0], true }
// Encrypt encrypts plaintext into ciphertext and protects ciphertext integrity // with a MAC. func (c *Crypter) Encrypt(data []byte) ([]byte, error) { block, err := aes.NewCipher(c.aesKey) if err != nil { return nil, err } ch, err := c.CreateHeader() if err != nil { return nil, err } // A ciphertext consists of an IV, encrypted bytes, and the output of // HMAC-SHA256. ciphertext := make([]byte, aes.BlockSize+len(data)) iv := ciphertext[:aes.BlockSize] if _, err := rand.Read(iv); err != nil { return nil, err } s := cipher.NewCTR(block, iv) s.XORKeyStream(ciphertext[aes.BlockSize:], data) mac := hmac.New(sha256.New, c.hmacKey) mac.Write(ciphertext) m := mac.Sum(nil) ed := &EncryptedData{ Header: ch, Iv: iv, Ciphertext: ciphertext[aes.BlockSize:], Mac: m, } return proto.Marshal(ed) }
// Decrypt checks the MAC then decrypts ciphertext into plaintext. func (c *Crypter) Decrypt(ciphertext []byte) ([]byte, error) { var ed EncryptedData if err := proto.Unmarshal(ciphertext, &ed); err != nil { return nil, err } // TODO(tmroeder): we're currently mostly ignoring the CryptoHeader, // since we only have one key. if *ed.Header.Version != CryptoVersion_CRYPTO_VERSION_1 { return nil, newError("bad version") } // Check the HMAC before touching the ciphertext. fullCiphertext := make([]byte, len(ed.Iv)+len(ed.Ciphertext)) copy(fullCiphertext, ed.Iv) copy(fullCiphertext[len(ed.Iv):], ed.Ciphertext) mac := hmac.New(sha256.New, c.hmacKey) mac.Write(fullCiphertext) m := mac.Sum(nil) if !hmac.Equal(m, ed.Mac) { return nil, newError("bad HMAC") } block, err := aes.NewCipher(c.aesKey) if err != nil { return nil, err } s := cipher.NewCTR(block, ed.Iv) data := make([]byte, len(ed.Ciphertext)) s.XORKeyStream(data, ed.Ciphertext) return data, nil }
// Encrypts a plaintext message with a temporary key and IV. func (m *Message) Encrypt() error { // Generate a new temporary key and the associated block cipher key := make([]byte, config.PacketCipherBits/8) if n, err := io.ReadFull(rand.Reader, key); n != len(key) || err != nil { return err } block, err := config.PacketCipher(key) if err != nil { return err } // Generate a new random counter mode IV and the associated stream cipher iv := make([]byte, block.BlockSize()) if n, err := io.ReadFull(rand.Reader, iv); n != len(iv) || err != nil { return err } stream := cipher.NewCTR(block, iv) // Encrypt the message, save the nonces and return stream.XORKeyStream(m.Data, m.Data) m.Head.Key = key m.Head.Iv = iv m.secure = true return nil }
// decrypt decrypts a value using the given Block in CTR mode. // // The value to be decrypted must have a length greater than the block size, // because the initialization vector is expected to prepend it. Also, a salt // with the length of the block size is expected to prepend the plain value. func decrypt(block cipher.Block, value []byte) (b []byte, err error) { // Recover in case block has an invalid key. defer func() { if r := recover(); r != nil { err = r.(error) } }() size := block.BlockSize() if len(value) > size { // Extract iv. iv := value[:size] // Extract ciphertext. value = value[size:] // Decrypt it. stream := cipher.NewCTR(block, iv) stream.XORKeyStream(value, value) if len(value) > size { // Return value without the salt. b = value[size:] return } } err = ErrDecryption return }
func AesEncryptData(data, key []byte, ctp string) []byte { block, err := aes.NewCipher(key) if err != nil { return nil } // The IV needs to be unique, but not secure. Therefore it's common to // include it at the beginning of the ciphertext. data_enc := make([]byte, aes.BlockSize+len(data)) iv := data_enc[:aes.BlockSize] if _, err := io.ReadFull(rand.Reader, iv); err != nil { return nil } var stream cipher.Stream switch ctp { case "cfb": stream = cipher.NewCFBEncrypter(block, iv) case "ctr": stream = cipher.NewCTR(block, iv) default: stream = cipher.NewOFB(block, iv) } stream.XORKeyStream(data_enc[aes.BlockSize:], data) // It's important to remember that ciphertexts must be authenticated // (i.e. by using crypto/hmac) as well as being encrypted in order to // be secure. return data_enc }
// Extracts a usable sized symmetric key and IV for the stream cipher from the huge master key, and // creates a CTR stream cipher. func (s *Session) makeCipher() (cipher.Stream, error) { // Create the key derivation function hasher := func() hash.Hash { return s.hash.New() } hkdf := hkdf.New(hasher, s.secret.Bytes(), hkdfSalt, hkdfInfo) // Extract the symmetric key key := make([]byte, s.keybits/8) n, err := io.ReadFull(hkdf, key) if n != len(key) || err != nil { return nil, err } // Create the block cipher block, err := s.crypter(key) if err != nil { return nil, err } // Extract the IV for the counter mode iv := make([]byte, block.BlockSize()) n, err = io.ReadFull(hkdf, iv) if n != len(iv) || err != nil { return nil, err } // Create the stream cipher return cipher.NewCTR(block, iv), nil }
func AesDecryptData(data, key []byte, ctp string) []byte { block, err := aes.NewCipher(key) if err != nil { return nil } if len(data) < aes.BlockSize { return nil } iv := data[:aes.BlockSize] data_dec := data[aes.BlockSize:] var stream cipher.Stream switch ctp { case "cfb": stream = cipher.NewCFBDecrypter(block, iv) case "ctr": stream = cipher.NewCTR(block, iv) default: stream = cipher.NewOFB(block, iv) } // XORKeyStream can work in-place if the two arguments are the same. stream.XORKeyStream(data_dec, data_dec) return data_dec }
func newAESCTR(key, iv []byte) (cipher.Stream, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err } return cipher.NewCTR(c, iv), nil }
func AesDecryptFd(inFile, outFile *os.File, key, iv []byte, ctp int) error { block, err := aes.NewCipher(key) if err != nil { return err } var stream cipher.Stream switch ctp { case 1: stream = cipher.NewCFBDecrypter(block, iv[:]) case 2: stream = cipher.NewCTR(block, iv[:]) default: stream = cipher.NewOFB(block, iv[:]) } reader := &cipher.StreamReader{S: stream, R: inFile} // Copy the input file to the output file, decrypting as we go. if _, err := io.Copy(outFile, reader); err != nil { return err } // Note that this example is simplistic in that it omits any // authentication of the encrypted data. If you were actually to use // StreamReader in this manner, an attacker could flip arbitrary bits in // the output. return nil }
// Decrypt decrypts a value using the given key with AES. // // The value to be decrypted must be prepended by a initialization vector // (http://goo.gl/zF67k) with the length of the block size. func Decrypt(blockKey []byte, value []byte) ([]byte, error) { block, err := aes.NewCipher(blockKey) if err != nil { return nil, err } size := block.BlockSize() if len(value) > size { // Extract iv. iv := value[:size] // Extract ciphertext. value = value[size:] // Decrypt it. stream := cipher.NewCTR(block, iv) stream.XORKeyStream(value, value) // Return on success return value, nil } return nil, errors.New("the value could not be decrypted") }
func secureInProxy(in <-chan []byte, secureIn chan<- []byte, hashType string, tIV, tCKey, tMKey []byte) { theirBlock, _ := aes.NewCipher(tCKey) theirCipher := cipher.NewCTR(theirBlock, tIV) theirMac, macSize := makeMac(hashType, tMKey) for { data, ok := <-in if !ok { close(secureIn) return } if len(data) <= macSize { continue } mark := len(data) - macSize buff := make([]byte, mark) theirCipher.XORKeyStream(buff, data[0:mark]) theirMac.Write(data[0:mark]) expected := theirMac.Sum(nil) theirMac.Reset() hmacOk := hmac.Equal(data[mark:], expected) if hmacOk { secureIn <- buff } else { secureIn <- nil } } }
func (c *Conversation) generateDHCommit() []byte { _, err := io.ReadFull(c.rand(), c.r[:]) if err != nil { panic("otr: short read from random source") } var xBytes [dhPrivateBytes]byte c.x = c.randMPI(xBytes[:]) c.gx = new(big.Int).Exp(g, c.x, p) c.gy = nil c.gxBytes = appendMPI(nil, c.gx) h := sha256.New() h.Write(c.gxBytes) h.Sum(c.digest[:0]) aesCipher, err := aes.NewCipher(c.r[:]) if err != nil { panic(err.Error()) } var iv [aes.BlockSize]byte ctr := cipher.NewCTR(aesCipher, iv[:]) ctr.XORKeyStream(c.gxBytes, c.gxBytes) return c.serializeDHCommit() }
func secureOutProxy(out chan<- []byte, secureOut <-chan []byte, hashType string, mIV, mCKey, mMKey []byte) { myBlock, _ := aes.NewCipher(mCKey) myCipher := cipher.NewCTR(myBlock, mIV) myMac, macSize := makeMac(hashType, mMKey) for { data, ok := <-secureOut if !ok { close(out) return } if len(data) == 0 { continue } buff := make([]byte, len(data)+macSize) myCipher.XORKeyStream(buff, data) myMac.Write(buff[0:len(data)]) copy(buff[len(data):], myMac.Sum(nil)) myMac.Reset() out <- buff } }
func (v *Vault) DecryptEnvironments(password string) (map[string]Environment, error) { if v.MACDigest != "sha-256" && v.Cipher != "aes" && v.CipherMode != "ctr" { return nil, ErrInvalidEncryptionConfig } // derive the key key, err := v.KeyDetails.key(password) if err != nil { return nil, err } // validate the mac if !hmac.Equal(v.mac(key), v.MAC) { return nil, ErrInvalidPassword } // decrypt the environments plaintext := make([]byte, len(v.Environments)) block, err := aes.NewCipher(key) decrypter := cipher.NewCTR(block, v.IV) decrypter.XORKeyStream(plaintext, v.Environments) // unmarshal the environments environments := map[string]Environment{} err = json.Unmarshal(plaintext, &environments) if err != nil { return nil, err } return environments, nil }
// encode uses the given block cipher (in CTR mode) to encrypt the // data, along with a hash, returning the iv and the ciphertext. What // is returned looks like: // // encrypted(salt + sessionData) + iv + hmac // func encode(block cipher.Block, hmac hash.Hash, data []byte) ([]byte, error) { buf := bytes.NewBuffer(nil) salt := make([]byte, block.BlockSize()) if _, err := io.ReadFull(rand.Reader, salt); err != nil { return nil, err } buf.Write(salt) buf.Write(data) session := buf.Bytes() iv := make([]byte, block.BlockSize()) if _, err := rand.Read(iv); err != nil { return nil, err } stream := cipher.NewCTR(block, iv) stream.XORKeyStream(session, session) buf.Write(iv) hmac.Write(buf.Bytes()) buf.Write(hmac.Sum(nil)) return buf.Bytes(), nil }