encrypts blocks when uploading original content

This commit is contained in:
Marcin Czenko 2025-07-03 17:26:14 +02:00
parent 0b77578eaf
commit 3c390f7aa2
No known key found for this signature in database
GPG Key ID: 33DEA0C8E30937C0
3 changed files with 18 additions and 4 deletions

View File

@ -27,12 +27,15 @@ type CodexEncryption* = ref object
masterKey: seq[byte]
proc newCodexEncryption*(): CodexEncryption =
let masterKey = newSeqWith(32, Rng.instance.rand(uint8.high).byte)
let masterKey = newSeqWith(MasterKeySize, Rng.instance.rand(uint8.high).byte)
CodexEncryption(masterKey: masterKey)
proc newCodexEncryption*(masterKey: seq[byte]): CodexEncryption =
CodexEncryption(masterKey: masterKey)
proc getKeyHexEncoded*(self: CodexEncryption): string =
self.masterKey.toHex()
proc deriveKeyForBlockIndex(self: CodexEncryption, blockIndex: uint32): seq[byte] =
let blockIndexArray = toBytes(blockIndex, bigEndian)
bearSslHash(

View File

@ -46,6 +46,7 @@ import ./errors
import ./logutils
import ./utils/asynciter
import ./utils/trackedfutures
import ./encryption/codexencryption
export logutils
@ -403,6 +404,7 @@ proc store*(
filename: ?string = string.none,
mimetype: ?string = string.none,
blockSize = DefaultBlockSize,
encryption: CodexEncryption,
): Future[?!Cid] {.async.} =
## Save stream contents as dataset with given blockSize
## to nodes's BlockStore, and return Cid of its manifest
@ -416,15 +418,19 @@ proc store*(
var cids: seq[Cid]
var blockIndex = 0.uint32
try:
while (let chunk = await chunker.getBytes(); chunk.len > 0):
without mhash =? MultiHash.digest($hcodec, chunk).mapFailure, err:
let encryptedChunk = encryption.encryptBlock(chunk, blockIndex)
blockIndex.inc()
without mhash =? MultiHash.digest($hcodec, encryptedChunk).mapFailure, err:
return failure(err)
without cid =? Cid.init(CIDv1, dataCodec, mhash).mapFailure, err:
return failure(err)
without blk =? bt.Block.new(cid, chunk, verify = false):
without blk =? bt.Block.new(cid, encryptedChunk, verify = false):
return failure("Unable to init block from chunk!")
cids.add(cid)

View File

@ -39,6 +39,7 @@ import ../manifest
import ../streams/asyncstreamwrapper
import ../stores
import ../utils/options
import ../encryption/codexencryption
import ./coders
import ./json
@ -230,6 +231,9 @@ proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRoute
if filename.isSome and not isValidFilename(filename.get()):
return RestApiResponse.error(Http422, "The filename is not valid.")
# prepare encryption service
let encryption = newCodexEncryption()
# Here we could check if the extension matches the filename if needed
let reader = bodyReader.get()
@ -240,6 +244,7 @@ proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRoute
AsyncStreamWrapper.new(reader = AsyncStreamReader(reader)),
filename = filename,
mimetype = mimetype,
encryption = encryption,
)
), error:
error "Error uploading file", exc = error.msg
@ -247,7 +252,7 @@ proc initDataApi(node: CodexNodeRef, repoStore: RepoStore, router: var RestRoute
codex_api_uploads.inc()
trace "Uploaded file", cid
return RestApiResponse.response($cid)
return RestApiResponse.response($cid & ":" & encryption.getKeyHexEncoded())
except CancelledError:
trace "Upload cancelled error"
return RestApiResponse.error(Http500)