updates encryption docs

This commit is contained in:
Marcin Czenko 2025-06-30 14:19:35 +02:00
parent 806d410b1f
commit 2c06131396
No known key found for this signature in database
GPG Key ID: 33DEA0C8E30937C0
4 changed files with 102 additions and 1 deletions

View File

@ -0,0 +1,58 @@
Here is an example, of how to use hashing in [[BearSSL]]:
```nim
import bearssl/hash
import stew/byteutils
let data = "0123456789abcdef".toBytes
let buff = newSeq[byte](sha256SIZE)
var sha256HashCtx = Sha256Context()
sha256Init(sha256HashCtx)
sha224Update(sha256HashCtx, addr data[0], data.len.uint)
sha256Out(sha256HashCtx, addr buff[0])
echo "Hash out: ", buff.toHex
```
>[!note]
> notice that above we use `sha224Update` and not the expected `sha256update`. This is because of a bug, which is addressed here: https://github.com/status-im/nim-bearssl/pull/68
BearSSL also simulates an [OOP interface](https://bearssl.org/oop.html), which can be used to create a generic `hash` function which can then be reused for various hashing algorithms:
```nim
import bearssl/hash
proc hash(hashClass: ptr HashClass, data: openArray[byte]): seq[byte] =
var compatCtx = HashCompatContext()
let buffSize = (hashClass[].desc shr HASHDESC_OUT_OFF) and HASHDESC_OUT_MASK
result = newSeq[byte](buffSize)
let hashClassPtrPtr: ConstPtrPtrHashClass = addr(compatCtx.vtable)
hashClass[].init(hashClassPtrPtr)
hashClass[].update(hashClassPtrPtr, addr data[0], data.len.uint)
hashClass[].`out`(hashClassPtrPtr, addr result[0])
```
Then such a hash function can be conveniently reused for various hashing functions:
```nim
import stew/byteutils
let data = "0123456789abcdef".toBytes
var sha256HashCtx = Sha256Context()
sha256Init(sha256HashCtx)
echo "Hash out[sha256]: ", hash(sha256HashCtx.vtable, data).toHex
var sha1HashCtx = Sha1Context()
sha1Init(sha1HashCtx)
echo "Hash out[sha1]: ", hash(sha1HashCtx.vtable, data).toHex
var md5Ctx = Md5Context()
md5Init(md5Ctx)
echo "Hash out[md5]: ", hash(md5Ctx.vtable, data).toHex
```

View File

@ -20,7 +20,7 @@ I would argue that at the moment we should only do something very basic, that is
We need to choose a [stream cipher](https://en.wikipedia.org/wiki/Stream_cipher). Which one to choose doesn't really matter as long as we don't fuck up the many subtle details. Some natural options:
- something based on the [AES block cipher](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)
- [Salsa20](https://en.wikipedia.org/wiki/Salsa20) or ChaCha
- [Salsa20](https://en.wikipedia.org/wiki/Salsa20) or ChaCha (newer)
- just `XOR` with Shake or TurboShake (Shake is the SHA3 XOF)
AES is usually a default choice because it's a standard, it's well-known (you don't have to explain the choice), and hardware-accelerated. However, there are many details allowing you to shoot yourself in the foot.
@ -77,6 +77,8 @@ A common mitigation strategy is to include additional entropy based for example
## A proposal
^b2e265
Based on the above, I have a very simple proposal:
- use a freshly generated random master key (at least 256 bits) per dataset (generated and kept on the user's machine)

View File

@ -1,7 +1,27 @@
---
related-to:
- "[[Codex Encryption Basis]]"
- "[[How to get a pointer to a seq to pass it to a C library]]"
---
As summarized in [[Codex Encryption Basis#^b2e265|the proposal]], we:
- use a freshly generated random master key (at least 256 bits) per dataset (generated and kept on the user's machine)
- derive a new encryption key and also an IV for each block from the master key and the block index
- use for example AES192-CBC
For example, we could have
key = SHA256( MASTER_KEY || block_index ), truncated to 192 bits
IV = SHA256( MASTER_IV || block_index ), truncated to 128 bits
where both `MASTER_KEY` and `MASTER_IV` are 256 bit random numbers, and `||` denotes concatenation.
If storing 512 bits (as opposed to a 256 bit minimum) of key material is a problem, we could derive both by the same key, for example as
key' = SHA256( MASTER_KEY || 0x01 || block_index ), truncated to 192 bits
IV' = SHA256( MASTER_KEY || 0x02 || block_index ), truncated to 128 bits
Some context info:
- [bearssl](https://bearssl.org/)

View File

@ -0,0 +1,21 @@
Having a Nim sequence:
```nim
var buff = newSeq[byte](buffSize)
```
if you want to get a pointer to the underlying data buffer that is suitable for being passed to a C library, you can simply use:
```nim
sha256Update(ctx, addr buff[0], input[i].len.uint)
```
If your input is a `string`, you can use the following:
```nim
let str = "abcdefghijklmnopqrstuvwxyz"
sha256Update(ctx, str.cstring, input[i].len.uint)
```
Here we use `sha256Update` from [[BearSSL]] library. See [[BearSSL hashing]] for more complete examples.
See also [Accessing seq pointer](https://forum.nim-lang.org/t/1489) and [Use cstring for C binding](https://forum.nim-lang.org/t/8179) on Nim forum.