summaryrefslogtreecommitdiffstats
path: root/vendor/maunium.net/go/mautrix/crypto/utils/utils.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/maunium.net/go/mautrix/crypto/utils/utils.go')
-rw-r--r--vendor/maunium.net/go/mautrix/crypto/utils/utils.go133
1 files changed, 133 insertions, 0 deletions
diff --git a/vendor/maunium.net/go/mautrix/crypto/utils/utils.go b/vendor/maunium.net/go/mautrix/crypto/utils/utils.go
new file mode 100644
index 00000000..e320bca1
--- /dev/null
+++ b/vendor/maunium.net/go/mautrix/crypto/utils/utils.go
@@ -0,0 +1,133 @@
+// Copyright (c) 2020 Nikos Filippakis
+//
+// 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 utils
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/sha256"
+ "crypto/sha512"
+ "encoding/base64"
+ "math/rand"
+ "strings"
+
+ "golang.org/x/crypto/hkdf"
+ "golang.org/x/crypto/pbkdf2"
+
+ "maunium.net/go/mautrix/util/base58"
+)
+
+const (
+ // AESCTRKeyLength is the length of the AES256-CTR key used.
+ AESCTRKeyLength = 32
+ // AESCTRIVLength is the length of the AES256-CTR IV used.
+ AESCTRIVLength = 16
+ // HMACKeyLength is the length of the HMAC key used.
+ HMACKeyLength = 32
+ // SHAHashLength is the length of the SHA hash used.
+ SHAHashLength = 32
+)
+
+// XorA256CTR encrypts the input with the keystream generated by the AES256-CTR algorithm with the given arguments.
+func XorA256CTR(source []byte, key [AESCTRKeyLength]byte, iv [AESCTRIVLength]byte) []byte {
+ block, _ := aes.NewCipher(key[:])
+ cipher.NewCTR(block, iv[:]).XORKeyStream(source, source)
+ return source
+}
+
+// GenAttachmentA256CTR generates a new random AES256-CTR key and IV suitable for encrypting attachments.
+func GenAttachmentA256CTR() (key [AESCTRKeyLength]byte, iv [AESCTRIVLength]byte) {
+ _, err := rand.Read(key[:])
+ if err != nil {
+ panic(err)
+ }
+
+ // The last 8 bytes of the IV act as the counter in AES-CTR, which means they're left empty here
+ _, err = rand.Read(iv[:8])
+ if err != nil {
+ panic(err)
+ }
+ return
+}
+
+// GenA256CTRIV generates a random IV for AES256-CTR with the last bit set to zero.
+func GenA256CTRIV() (iv [AESCTRIVLength]byte) {
+ _, err := rand.Read(iv[:])
+ if err != nil {
+ panic(err)
+ }
+ iv[8] &= 0x7F
+ return
+}
+
+// DeriveKeysSHA256 derives an AES and a HMAC key from the given recovery key.
+func DeriveKeysSHA256(key []byte, name string) ([AESCTRKeyLength]byte, [HMACKeyLength]byte) {
+ var zeroBytes [32]byte
+
+ derivedHkdf := hkdf.New(sha256.New, key[:], zeroBytes[:], []byte(name))
+
+ var aesKey [AESCTRKeyLength]byte
+ var hmacKey [HMACKeyLength]byte
+ derivedHkdf.Read(aesKey[:])
+ derivedHkdf.Read(hmacKey[:])
+
+ return aesKey, hmacKey
+}
+
+// PBKDF2SHA512 generates a key of the given bit-length using the given passphrase, salt and iteration count.
+func PBKDF2SHA512(password []byte, salt []byte, iters int, keyLenBits int) []byte {
+ return pbkdf2.Key(password, salt, iters, keyLenBits/8, sha512.New)
+}
+
+// DecodeBase58RecoveryKey recovers the secret storage from a recovery key.
+func DecodeBase58RecoveryKey(recoveryKey string) []byte {
+ noSpaces := strings.ReplaceAll(recoveryKey, " ", "")
+ decoded := base58.Decode(noSpaces)
+ if len(decoded) != AESCTRKeyLength+3 { // AESCTRKeyLength bytes key and 3 bytes prefix / parity
+ return nil
+ }
+ var parity byte
+ for _, b := range decoded[:34] {
+ parity ^= b
+ }
+ if parity != decoded[34] || decoded[0] != 0x8B || decoded[1] != 1 {
+ return nil
+ }
+ return decoded[2:34]
+}
+
+// EncodeBase58RecoveryKey recovers the secret storage from a recovery key.
+func EncodeBase58RecoveryKey(key []byte) string {
+ var inputBytes [35]byte
+ copy(inputBytes[2:34], key[:])
+ inputBytes[0] = 0x8B
+ inputBytes[1] = 1
+
+ var parity byte
+ for _, b := range inputBytes[:34] {
+ parity ^= b
+ }
+ inputBytes[34] = parity
+ recoveryKey := base58.Encode(inputBytes[:])
+
+ var spacedKey string
+ for i, c := range recoveryKey {
+ if i > 0 && i%4 == 0 {
+ spacedKey += " "
+ }
+ spacedKey += string(c)
+ }
+ return spacedKey
+}
+
+// HMACSHA256B64 calculates the base64 of the SHA256 hmac of the input with the given key.
+func HMACSHA256B64(input []byte, hmacKey [HMACKeyLength]byte) string {
+ h := hmac.New(sha256.New, hmacKey[:])
+ h.Write(input)
+ return base64.StdEncoding.EncodeToString(h.Sum(nil))
+}