diff options
Diffstat (limited to 'vendor/go.mau.fi/whatsmeow/util')
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/util/cbcutil/cbc.go | 101 | ||||
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/util/hkdfutil/hkdf.go | 28 | ||||
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/util/keys/keypair.go | 75 | ||||
-rw-r--r-- | vendor/go.mau.fi/whatsmeow/util/log/log.go | 83 |
4 files changed, 287 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/whatsmeow/util/cbcutil/cbc.go b/vendor/go.mau.fi/whatsmeow/util/cbcutil/cbc.go new file mode 100644 index 00000000..05fa8577 --- /dev/null +++ b/vendor/go.mau.fi/whatsmeow/util/cbcutil/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 cbcutil + +/* +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/go.mau.fi/whatsmeow/util/hkdfutil/hkdf.go b/vendor/go.mau.fi/whatsmeow/util/hkdfutil/hkdf.go new file mode 100644 index 00000000..fbc97124 --- /dev/null +++ b/vendor/go.mau.fi/whatsmeow/util/hkdfutil/hkdf.go @@ -0,0 +1,28 @@ +// Copyright (c) 2021 Tulir Asokan +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Package hkdfutil contains a simple wrapper for golang.org/x/crypto/hkdf that reads a specified number of bytes. +package hkdfutil + +import ( + "crypto/sha256" + "fmt" + + "golang.org/x/crypto/hkdf" +) + +func SHA256(key, salt, info []byte, length uint8) []byte { + data := make([]byte, length) + h := hkdf.New(sha256.New, key, salt, info) + n, err := h.Read(data) + if err != nil { + // Length is limited to 255 by being uint8, so these errors can't actually happen + panic(fmt.Errorf("failed to expand key: %w", err)) + } else if uint8(n) != length { + panic(fmt.Errorf("didn't read enough bytes (got %d, wanted %d)", n, length)) + } + return data +} diff --git a/vendor/go.mau.fi/whatsmeow/util/keys/keypair.go b/vendor/go.mau.fi/whatsmeow/util/keys/keypair.go new file mode 100644 index 00000000..55679ff2 --- /dev/null +++ b/vendor/go.mau.fi/whatsmeow/util/keys/keypair.go @@ -0,0 +1,75 @@ +// Copyright (c) 2021 Tulir Asokan +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Package keys contains a utility struct for elliptic curve keypairs. +package keys + +import ( + "crypto/rand" + "fmt" + + "go.mau.fi/libsignal/ecc" + "golang.org/x/crypto/curve25519" +) + +type KeyPair struct { + Pub *[32]byte + Priv *[32]byte +} + +var _ ecc.ECPublicKeyable + +func NewKeyPairFromPrivateKey(priv [32]byte) *KeyPair { + var kp KeyPair + kp.Priv = &priv + var pub [32]byte + curve25519.ScalarBaseMult(&pub, kp.Priv) + kp.Pub = &pub + return &kp +} + +func NewKeyPair() *KeyPair { + var priv [32]byte + + _, err := rand.Read(priv[:]) + if err != nil { + panic(fmt.Errorf("failed to generate curve25519 private key: %w", err)) + } + + priv[0] &= 248 + priv[31] &= 127 + priv[31] |= 64 + + return NewKeyPairFromPrivateKey(priv) +} + +func (kp *KeyPair) CreateSignedPreKey(keyID uint32) *PreKey { + newKey := NewPreKey(keyID) + newKey.Signature = kp.Sign(&newKey.KeyPair) + return newKey +} + +func (kp *KeyPair) Sign(keyToSign *KeyPair) *[64]byte { + pubKeyForSignature := make([]byte, 33) + pubKeyForSignature[0] = ecc.DjbType + copy(pubKeyForSignature[1:], keyToSign.Pub[:]) + + signature := ecc.CalculateSignature(ecc.NewDjbECPrivateKey(*kp.Priv), pubKeyForSignature) + return &signature +} + +type PreKey struct { + KeyPair + KeyID uint32 + Signature *[64]byte +} + +func NewPreKey(keyID uint32) *PreKey { + return &PreKey{ + KeyPair: *NewKeyPair(), + KeyID: keyID, + } +} diff --git a/vendor/go.mau.fi/whatsmeow/util/log/log.go b/vendor/go.mau.fi/whatsmeow/util/log/log.go new file mode 100644 index 00000000..2662cdea --- /dev/null +++ b/vendor/go.mau.fi/whatsmeow/util/log/log.go @@ -0,0 +1,83 @@ +// Copyright (c) 2021 Tulir Asokan +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +// Package waLog contains a simple logger interface used by the other whatsmeow packages. +package waLog + +import ( + "fmt" + "strings" + "time" +) + +// Logger is a simple logger interface that can have subloggers for specific areas. +type Logger interface { + Warnf(msg string, args ...interface{}) + Errorf(msg string, args ...interface{}) + Infof(msg string, args ...interface{}) + Debugf(msg string, args ...interface{}) + Sub(module string) Logger +} + +type noopLogger struct{} + +func (n *noopLogger) Errorf(_ string, _ ...interface{}) {} +func (n *noopLogger) Warnf(_ string, _ ...interface{}) {} +func (n *noopLogger) Infof(_ string, _ ...interface{}) {} +func (n *noopLogger) Debugf(_ string, _ ...interface{}) {} +func (n *noopLogger) Sub(_ string) Logger { return n } + +// Noop is a no-op Logger implementation that silently drops everything. +var Noop Logger = &noopLogger{} + +type stdoutLogger struct { + mod string + color bool + min int +} + +var colors = map[string]string{ + "INFO": "\033[36m", + "WARN": "\033[33m", + "ERROR": "\033[31m", +} + +var levelToInt = map[string]int{ + "": -1, + "DEBUG": 0, + "INFO": 1, + "WARN": 2, + "ERROR": 3, +} + +func (s *stdoutLogger) outputf(level, msg string, args ...interface{}) { + if levelToInt[level] < s.min { + return + } + var colorStart, colorReset string + if s.color { + colorStart = colors[level] + colorReset = "\033[0m" + } + fmt.Printf("%s%s [%s %s] %s%s\n", time.Now().Format("15:04:05.000"), colorStart, s.mod, level, fmt.Sprintf(msg, args...), colorReset) +} + +func (s *stdoutLogger) Errorf(msg string, args ...interface{}) { s.outputf("ERROR", msg, args...) } +func (s *stdoutLogger) Warnf(msg string, args ...interface{}) { s.outputf("WARN", msg, args...) } +func (s *stdoutLogger) Infof(msg string, args ...interface{}) { s.outputf("INFO", msg, args...) } +func (s *stdoutLogger) Debugf(msg string, args ...interface{}) { s.outputf("DEBUG", msg, args...) } +func (s *stdoutLogger) Sub(mod string) Logger { + return &stdoutLogger{mod: fmt.Sprintf("%s/%s", s.mod, mod), color: s.color, min: s.min} +} + +// Stdout is a simple Logger implementation that outputs to stdout. The module name given is included in log lines. +// +// minLevel specifies the minimum log level to output. An empty string will output all logs. +// +// If color is true, then info, warn and error logs will be colored cyan, yellow and red respectively using ANSI color escape codes. +func Stdout(module string, minLevel string, color bool) Logger { + return &stdoutLogger{mod: module, color: color, min: levelToInt[strings.ToUpper(minLevel)]} +} |