|
| 1 | +## Nim-Codex |
| 2 | +## Copyright (c) 2025 Status Research & Development GmbH |
| 3 | +## Licensed under either of |
| 4 | +## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE)) |
| 5 | +## * MIT license ([LICENSE-MIT](LICENSE-MIT)) |
| 6 | +## at your option. |
| 7 | +## This file may not be copied, modified, or distributed except according to |
| 8 | +## those terms. |
| 9 | + |
| 10 | +import std/sequtils |
| 11 | +import bearssl/[blockx, hash] |
| 12 | +import stew/[byteutils, endians2] |
| 13 | + |
| 14 | +import ../rng |
| 15 | +import ./bearsslhash |
| 16 | + |
| 17 | +{.push raises: [].} |
| 18 | + |
| 19 | +const |
| 20 | + MasterKeySize = 32 # 256 bits |
| 21 | + KeySize = 24 # 192 bits for AES-192 |
| 22 | + IvSize = 16 # 128 bits |
| 23 | + KeyDerivationIdentifier = "aes192_block_key".toBytes |
| 24 | + IvDerivationIdentifier = "aes192_block_iv".toBytes |
| 25 | + |
| 26 | +type CodexEncryption* = ref object |
| 27 | + masterKey: seq[byte] |
| 28 | + |
| 29 | +proc newCodexEncryption*(): CodexEncryption = |
| 30 | + let masterKey = newSeqWith(32, Rng.instance.rand(uint8.high).byte) |
| 31 | + CodexEncryption(masterKey: masterKey) |
| 32 | + |
| 33 | +proc newCodexEncryption*(masterKey: seq[byte]): CodexEncryption = |
| 34 | + CodexEncryption(masterKey: masterKey) |
| 35 | + |
| 36 | +proc deriveKeyForBlockIndex(self: CodexEncryption, blockIndex: uint32): seq[byte] = |
| 37 | + let blockIndexArray = toBytes(blockIndex, bigEndian) |
| 38 | + bearSslHash( |
| 39 | + addr sha256Vtable, self.masterKey & KeyDerivationIdentifier & blockIndexArray.toSeq |
| 40 | + )[0 ..< KeySize] |
| 41 | + |
| 42 | +proc deriveIvForBlockIndex(self: CodexEncryption, blockIndex: uint32): seq[byte] = |
| 43 | + let blockIndexArray = toBytes(blockIndex, bigEndian) |
| 44 | + bearSslHash( |
| 45 | + addr sha256Vtable, self.masterKey & IvDerivationIdentifier & blockIndexArray.toSeq |
| 46 | + )[0 ..< IvSize] |
| 47 | + |
| 48 | +proc encryptBlock*( |
| 49 | + self: CodexEncryption, blockData: seq[byte], blockIndex: uint32 |
| 50 | +): seq[byte] = |
| 51 | + let key = self.deriveKeyForBlockIndex(blockIndex) |
| 52 | + let iv = self.deriveIvForBlockIndex(blockIndex) |
| 53 | + result = blockData |
| 54 | + |
| 55 | + var encCtx: AesBigCbcencKeys |
| 56 | + aesBigCbcencInit(encCtx, addr key[0], key.len.uint) |
| 57 | + aesBigCbcencRun(encCtx, addr iv[0], addr result[0], iv.len.uint) |
| 58 | + |
| 59 | +proc decryptBlock*( |
| 60 | + self: CodexEncryption, encryptedBlockData: seq[byte], blockIndex: uint32 |
| 61 | +): seq[byte] = |
| 62 | + let key = self.deriveKeyForBlockIndex(blockIndex) |
| 63 | + let iv = self.deriveIvForBlockIndex(blockIndex) |
| 64 | + result = encryptedBlockData |
| 65 | + |
| 66 | + var decCtx: AesBigCbcdecKeys |
| 67 | + aesBigCbcdecInit(decCtx, addr key[0], key.len.uint) |
| 68 | + aesBigCbcdecRun(decCtx, addr iv[0], addr result[0], iv.len.uint) |
0 commit comments