diff options
Diffstat (limited to 'vendor/github.com/Rhymen/go-whatsapp/crypto')
3 files changed, 197 insertions, 0 deletions
diff --git a/vendor/github.com/Rhymen/go-whatsapp/crypto/cbc/cbc.go b/vendor/github.com/Rhymen/go-whatsapp/crypto/cbc/cbc.go new file mode 100644 index 00000000..cc5427c3 --- /dev/null +++ b/vendor/github.com/Rhymen/go-whatsapp/crypto/cbc/cbc.go @@ -0,0 +1,101 @@ +/* +CBC describes a block cipher mode. In cryptography, a block cipher mode of operation is an algorithm that uses a +block cipher to provide an information service such as confidentiality or authenticity. A block cipher by itself +is only suitable for the secure cryptographic transformation (encryption or decryption) of one fixed-length group of +bits called a block. A mode of operation describes how to repeatedly apply a cipher's single-block operation to +securely transform amounts of data larger than a block. + +This package simplifies the usage of AES-256-CBC. +*/ +package cbc + +/* +Some code is provided by the GitHub user locked (github.com/locked): +https://gist.github.com/locked/b066aa1ddeb2b28e855e +Thanks! +*/ +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "fmt" + "io" +) + +/* +Decrypt is a function that decrypts a given cipher text with a provided key and initialization vector(iv). +*/ +func Decrypt(key, iv, ciphertext []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + + if err != nil { + return nil, err + } + + if len(ciphertext) < aes.BlockSize { + return nil, fmt.Errorf("ciphertext is shorter then block size: %d / %d", len(ciphertext), aes.BlockSize) + } + + if iv == nil { + iv = ciphertext[:aes.BlockSize] + ciphertext = ciphertext[aes.BlockSize:] + } + + cbc := cipher.NewCBCDecrypter(block, iv) + cbc.CryptBlocks(ciphertext, ciphertext) + + return unpad(ciphertext) +} + +/* +Encrypt is a function that encrypts plaintext with a given key and an optional initialization vector(iv). +*/ +func Encrypt(key, iv, plaintext []byte) ([]byte, error) { + plaintext = pad(plaintext, aes.BlockSize) + + if len(plaintext)%aes.BlockSize != 0 { + return nil, fmt.Errorf("plaintext is not a multiple of the block size: %d / %d", len(plaintext), aes.BlockSize) + } + + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + var ciphertext []byte + if iv == nil { + ciphertext = make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + + cbc := cipher.NewCBCEncrypter(block, iv) + cbc.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) + } else { + ciphertext = make([]byte, len(plaintext)) + + cbc := cipher.NewCBCEncrypter(block, iv) + cbc.CryptBlocks(ciphertext, plaintext) + } + + return ciphertext, nil +} + +func pad(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, padtext...) +} + +func unpad(src []byte) ([]byte, error) { + length := len(src) + padLen := int(src[length-1]) + + if padLen > length { + return nil, fmt.Errorf("padding is greater then the length: %d / %d", padLen, length) + } + + return src[:(length - padLen)], nil +} diff --git a/vendor/github.com/Rhymen/go-whatsapp/crypto/curve25519/curve.go b/vendor/github.com/Rhymen/go-whatsapp/crypto/curve25519/curve.go new file mode 100644 index 00000000..5ddf9c9a --- /dev/null +++ b/vendor/github.com/Rhymen/go-whatsapp/crypto/curve25519/curve.go @@ -0,0 +1,44 @@ +/* +In cryptography, Curve25519 is an elliptic curve offering 128 bits of security and designed for use with the elliptic +curve Diffie–Hellman (ECDH) key agreement scheme. It is one of the fastest ECC curves and is not covered by any known +patents. The reference implementation is public domain software. The original Curve25519 paper defined it +as a Diffie–Hellman (DH) function. +*/ +package curve25519 + +import ( + "crypto/rand" + "golang.org/x/crypto/curve25519" + "io" +) + +/* +GenerateKey generates a public private key pair using Curve25519. +*/ +func GenerateKey() (privateKey *[32]byte, publicKey *[32]byte, err error) { + var pub, priv [32]byte + + _, err = io.ReadFull(rand.Reader, priv[:]) + if err != nil { + return nil, nil, err + } + + priv[0] &= 248 + priv[31] &= 127 + priv[31] |= 64 + + curve25519.ScalarBaseMult(&pub, &priv) + + return &priv, &pub, nil +} + +/* +GenerateSharedSecret generates the shared secret with a given public private key pair. +*/ +func GenerateSharedSecret(priv, pub [32]byte) []byte { + var secret [32]byte + + curve25519.ScalarMult(&secret, &priv, &pub) + + return secret[:] +} diff --git a/vendor/github.com/Rhymen/go-whatsapp/crypto/hkdf/hkdf.go b/vendor/github.com/Rhymen/go-whatsapp/crypto/hkdf/hkdf.go new file mode 100644 index 00000000..e0be0587 --- /dev/null +++ b/vendor/github.com/Rhymen/go-whatsapp/crypto/hkdf/hkdf.go @@ -0,0 +1,52 @@ +/* +HKDF is a simple key derivation function (KDF) based on +a hash-based message authentication code (HMAC). It was initially proposed by its authors as a building block in +various protocols and applications, as well as to discourage the proliferation of multiple KDF mechanisms. +The main approach HKDF follows is the "extract-then-expand" paradigm, where the KDF logically consists of two modules: +the first stage takes the input keying material and "extracts" from it a fixed-length pseudorandom key, and then the +second stage "expands" this key into several additional pseudorandom keys (the output of the KDF). +*/ +package hkdf + +import ( + "crypto/hmac" + "crypto/sha256" + "fmt" + "golang.org/x/crypto/hkdf" + "io" +) + +/* +Expand expands a given key with the HKDF algorithm. +*/ +func Expand(key []byte, length int, info string) ([]byte, error) { + if info == "" { + keyBlock := hmac.New(sha256.New, key) + var out, last []byte + + var blockIndex byte = 1 + for i := 0; len(out) < length; i++ { + keyBlock.Reset() + //keyBlock.Write(append(append(last, []byte(info)...), blockIndex)) + keyBlock.Write(last) + keyBlock.Write([]byte(info)) + keyBlock.Write([]byte{blockIndex}) + last = keyBlock.Sum(nil) + blockIndex += 1 + out = append(out, last...) + } + return out[:length], nil + } else { + h := hkdf.New(sha256.New, key, nil, []byte(info)) + out := make([]byte, length) + n, err := io.ReadAtLeast(h, out, length) + if err != nil { + return nil, err + } + if n != length { + return nil, fmt.Errorf("new key to short") + } + + return out[:length], nil + } +} |