diff --git a/blobsets.nimble b/blobsets.nimble index ba31766..f0efed1 100644 --- a/blobsets.nimble +++ b/blobsets.nimble @@ -1,12 +1,12 @@ # Package -version = "0.1.2" +version = "0.2.0" author = "Emery Hemingway" description = "Sets of named blobs" license = "AGPLv3" srcDir = "src" -requires "nim >= 0.18.0", "cbor >= 0.5.2", "siphash", "spryvm", "toxcore" +requires "nim >= 0.18.0", "base32", "cbor >= 0.5.2", "siphash", "tiger >= 0.2.1" -bin = @["blobset", "blobserver"] +bin = @["blobingest", "blobset", "blobserver"] skipFiles = @["blobset.nim", "blobserver.nim"] diff --git a/default.nix b/default.nix index dcb06b2..472ef0a 100644 --- a/default.nix +++ b/default.nix @@ -5,11 +5,18 @@ stdenv.mkDerivation { src = ./.; + base32 = fetchFromGitHub { + owner = "ehmry"; + repo = "base32.nim"; + rev = "c557fd9e1d09d103f3781b6eba5fa22330579425"; + sha256 = "081rlflad99f4krlsfgll6f5l09w3a2i4zgfwncxya5hn6jhfg32"; + }; + cbor = fetchFromGitHub { owner = "ehmry"; repo = "nim-cbor"; - rev = "v0.5.2"; - sha256 = "0fh8vriad6nvjl3fxl2b62bk7y4z1hx90527a530nln5g1cj9z8f"; + rev = "v0.6.0"; + sha256 = "175h3vk0qccmzymlbqdwni645d7v5zz0fn6zdjsy1pd88kg5v66h"; }; siphash = fetchFromGitHub { @@ -19,13 +26,20 @@ stdenv.mkDerivation { sha256 = "1z4xm3ckygw8pmn9b6axdk65ib1y5bgwa3v1dbxamvhjmyfr62w4"; }; + tiger = fetchFromGitHub { + owner = "ehmry"; + repo = "tiger"; + rev = "v0.2"; + sha256 = "0hn3ccmmfgkmiz5q2mvlyhgc22054i54m211ai2a9k9k37w7w2hz"; + }; + buildInputs = [ nim pcre ]; NIX_LDFLAGS = [ "-lpcre" ]; buildPhase = '' HOME=$TMPDIR - nim c -p:$cbor/src -p:$siphash/src -d:release src/blobset.nim + nim c -p:$base32 -p:$cbor/src -p:$siphash/src -p:$tiger -d:release src/blobset.nim ''; installPhase = "install -Dt $out/bin src/blobset"; diff --git a/src/blobset.nim b/src/blobset.nim index 64109a2..de8e9be 100644 --- a/src/blobset.nim +++ b/src/blobset.nim @@ -6,19 +6,6 @@ import cbor import ./blobsets, ./blobsets/filestores, ./blobsets/httpservers, ./blobsets/httpstores -when defined(tox): - import toxcore - -# Basic Spry -when defined(spry): - import spryvm/spryvm - - # Spry extra modules - import spryvm/sprycore, spryvm/spryextend, spryvm/sprymath, spryvm/spryos, spryvm/spryio, - spryvm/spryoo, spryvm/sprystring, spryvm/sprymodules, spryvm/spryreflect, spryvm/sprymemfile, - spryvm/spryblock, - ./blobsets/spryblobs - import os, strutils when defined(readLine): import rdstdin, linenoise @@ -34,115 +21,6 @@ proc openStore(): BlobStore = else: newFileStore(url) -when defined(spry): - proc newSpry(store: BlobStore): Interpreter = - result = newInterpreter() - result.addCore() - result.addExtend() - result.addMath() - result.addOS() - result.addIO() - result.addOO() - result.addString() - result.addModules() - result.addReflect() - result.addMemfile() - result.addBlock() - result.addBlobSets(store) - discard result.evalRoot("""[loadFile: "blobs.sy"]""") - -when defined(tox) and defined(spry): - type IngestTransfer = object - name: string - stream: IngestStream - size, pos: uint64 - - proc process( - t: var IngestTransfer; tox: Tox; friend: Friend; file: FileTransfer; - pos: uint64; data: pointer; size: int): bool = - ## Process transfer data, return true if transfer is complete - if t.pos != pos: - cancel t.stream - tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) - discard tox.send(friend, """stream is at position $# but you sent $#""" % [$t.pos, $pos]) - result = true - else: - waitFor t.stream.ingest(data, size) - t.pos.inc size - if t.pos >= t.size: - let blobId, blobSize = waitFor t.stream.finish() - discard tox.send(friend, """$# $# $#""" % [t.name, $blobId, $blobSize]) - result = true - - type Transfer = uint64 - proc `+`(friend: Friend; file: FileTransfer): Transfer = - (friend.Transfer shl 32) or file.Transfer - - proc setupCallbacks(tox: Tox) = - tox.onSelfConnectionStatus do (status: TOX_CONNECTION): - echo "self status is ", status - tox.onFriendRequest do (key: PublicKey; msg: string): - echo "friend request from ", key, ", ", msg - discard tox.addFriendNoRequest(key) - block: - let - store = openStore() - spry = newSpry(store) - transfers = newTable[Transfer, IngestTransfer](16) - tox.onFriendMessage do (friend: Friend; msg: string; kind: TOX_MESSAGE_TYPE): - try: - if kind == TOX_MESSAGE_TYPE_NORMAL: - tox.typing(friend, true) - let res = spry.evalRoot("[" & msg & "]") - tox.typing(friend, false) - discard tox.send(friend, $res, TOX_MESSAGE_TYPE_ACTION) - except: - discard tox.send(friend, getCurrentExceptionMsg()) - tox.onFileRecv do (friend: Friend; file: FileTransfer; kind: uint32; size: uint64; filename: string): - case kind - of (uint32)TOX_FILE_KIND_AVATAR: - tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) - else: - if transfers.len > 16: - tox.control(friend, file, TOX_FILE_CONTROL_CANCEL) - discard tox.send(friend, "too many transfers are pending") - else: - let msg = """you are trying to send me "$#", type $#, size $#""" % - [filename, $kind, $size] - discard tox.send(friend, msg) - transfers[friend+file] = IngestTransfer( - name: filename, - stream: store.openIngestStream(size.BiggestInt), - size: size) - tox.control(friend, file, TOX_FILE_CONTROL_RESUME) - tox.onFileRecvChunk do (friend: Friend; file: FileTransfer; pos: uint64; data: pointer; size: int): - try: - if transfers[friend+file].process(tox, friend, file, pos, data, size): - transfers.del(friend+file) - except: - discard tox.send(friend, getCurrentExceptionMsg(), TOX_MESSAGE_TYPE_ACTION) - - tox.name = "blobbot" - echo "/connect 127.0.0.1 ", tox.udpPort, " ", tox.dhtId - echo "/add ", tox.address - - proc toxMain() {.async.} = - let tox = newTox do (o: Options): - o.ipv6Enabled = false - o.localDiscoveryEnabled = true - o.holePunchingEnabled = false - var saveData = "" - try: saveData = readFile "tox.save" - except: discard - if saveData != "": - o.saveData = saveData - o.saveDataType = TOX_SAVEDATA_TYPE_TOX_SAVE - writeFile "tox.save", tox.saveData - setupCallbacks(tox) - while not tox.isClosed: - iterate tox - await sleepAsync(tox.iterationInterval) - proc serverMain(): Future[void] = let store = newFileStore("/tmp/blobs") @@ -943,67 +821,6 @@ proc getLine(prompt: string): string = stdout.write(prompt) result = stdin.readline() -when defined(spry): - proc spryMain() = - let spry = newSpry(openStore()) - var - lines, stashed, fileLines = newSeq[string]() - suspended: bool = true - - echo "Welcome to interactive Spry!" - echo "An empty line will evaluate previous lines, so hit enter twice." - # We collect lines until an empty line is entered, easy way to enter - # multiline code. - - while true: - var line: string - if suspended: - line = getLine(Prompt) - else: - if fileLines.len == 0: - quit 0 - # Read a line, eh, would be nice with removeFirst or popFirst... - line = fileLines[0] - fileLines.delete(0) - # Logic for pausing - if line.strip() == "# pause": - var enter = getLine(" ") - if enter.strip() == "s": - stdout.write(" \n") - stashed = lines - lines = newSeq[string]() - suspended = true - continue - else: - stdout.write(line & "\n") - - # Logic to start the script again - if suspended and line.strip() == "c": - lines = stashed - suspended = false - continue - - # Finally time to eval - if line.strip().len() == 0: - let code = lines.join("\n") - lines = newSeq[string]() - try: - # Let the interpreter eval the code. We need to eval whatever we - # get (ispry acting as a func). The surrounding block is just because we only - # want to pass one Node. - var result = spry.evalRoot("[" & code & "]") - #discard spry.setBinding(newEvalWord("@"), result) - var output = $result - # Print any result - if output.isNil: - output = if suspended: "nil" else: "" - stdout.write(output & "\n") - except: - echo "Oops, sorry about that: " & getCurrentExceptionMsg() & "\n" - echo getStackTrace() - else: - lines.add(line) - when isMainModule: var cmd = "" for kind, key, val in getopt(): @@ -1017,17 +834,6 @@ when isMainModule: of "dump": dumpMain() of "ingest": waitFor ingestMain() of "server": waitFor serverMain() - of "spry": - when defined(spry): - spryMain() - else: - quit "not compiled with Spry interpreter" of "check": waitFor checkMain() of "replicate": waitFor replicateMain() - of "tox": - when defined(tox) and defined(spry): - #waitFor toxReplicateMain() - waitFor toxMain() - else: - quit "not compiled with Tox node" else: quit("no such subcommand " & cmd) diff --git a/src/blobset.nim.cfg b/src/blobset.nim.cfg index 06ab0dd..18e6652 100644 --- a/src/blobset.nim.cfg +++ b/src/blobset.nim.cfg @@ -1,5 +1,2 @@ # Disable this to use only primitive stdin -d:readLine ---nilseqs:on --d:spry --d:tox diff --git a/src/blobsets.nim b/src/blobsets.nim index 257a7d2..18b65d4 100644 --- a/src/blobsets.nim +++ b/src/blobsets.nim @@ -1,53 +1,41 @@ -import std/asyncdispatch, std/asyncstreams -import std/hashes, std/streams, std/strutils, std/bitops, std/unicode, std/endians -import std/streams, std/strutils, std/random -import cbor, siphash +import ./blobsets/priv/hex +import base32, cbor, siphash, tiger -import ./blobsets/priv/hex, ./blobsets/priv/nimcrypto, ./blobsets/priv/nimcrypto/blake2 +import std/asyncdispatch, std/asyncstreams +import std/hashes, std/streams, std/strutils, std/bitops, std/unicode, std/endians, std/random const - digestLen* = 32 + digestSize* = 24 ## Length of a chunk digest. - cidSize* = digestLen - ## Size of CID object in memory - blobLeafSize* = 1 shl 14 - ## Size of blob leaves. - blobLeafSizeMask* = not(not(0) shl 14) - blobHexLen* = 32 * 2 - blobVisualLen* = 32 * 3 + blobLeafSize* = 1 shl 10 + ## Size of blob hash leaves (THEX/ADC). + blobLeafSizeMask* = blobLeafSize - 1 + blobHexLen* = digestSize * 2 + blobBase32Len* = (digestSize * 5 div 3) - 1 + blobVisualLen* = digestSize * 3 type - Blake2b256* = Blake2bContext[256] - - BlobId* = MDigest[Blake2b256.bits] + BlobId* = TigerDigest ## Blob Identifier - SetId* = MDigest[Blake2b256.bits] + SetId* = TigerDigest ## Set Identifier - Cid* {.deprecated} = BlobId - -func `$`*(bh: BlobId): string = - ## Convert a blob hash to a visual representation. - const baseRune = 0x2800 - result = newString(blobVisualLen) - var pos = 0 - for b in bh.data.items: - let r = (Rune)baseRune or b.int - fastToUTF8Copy(r, result, pos, true) - func parseStringId[T](s: string): T = case s.len of blobHexLen: hex.decode s, result.data + of blobBase32Len: + var tmp = base32.decode(s) + copyMem(result.data[0].addr, tmp[0].addr, digestSize) of blobVisualLen: var pos: int r: Rune for b in result.data.mitems: fastRuneAt(s, pos, r, true) - b = r.byte + b = byte(r.int and 0xff) else: - raise newException(ValueError, "invalid blobset id encoding") + raise newException(ValueError, "invalid blobset id encoding of len " & $s.len) func parseCborId[T](c: CborNode): T = ## Parse a CBOR node to binary. @@ -59,10 +47,6 @@ func toBlobId*(s: string): BlobId = ## Parse a visual blob hash to binary. parseStringId[BlobId] s -func toBlobId(c: CborNode): BlobId = - ## Parse a CBOR blob hash to binary. - parseCborId[BlobId] c - func toSetId*(s: string): SetId = ## Parse a visual set hash to binary. parseStringId[SetId] s @@ -77,7 +61,7 @@ proc `==`*(x, y: BlobId): bool = x.data == y.data proc `==`*(cbor: CborNode; cid: BlobId): bool = ## Compare a CBOR node with a BlobId. if cbor.kind == cborBytes: - for i in 0.. 1: - nodeOffset = 0 - inc nodeDepth + while 1 < len: var pos, next: int - while pos < len: - ctx.init do (params: var Blake2bParams): - params.fanout = 2 - params.depth = 255 - params.leafLength = blobLeafSize - params.nodeOffset = nodeOffset - params.nodeDepth = nodeDepth - inc nodeOffset - ctx.update(leaves[pos].data) - inc pos - if pos < len: - ctx.update(leaves[pos].data) - inc pos + while pos+1 < len: + init ctx + ctx.update [1'u8] + ctx.update leaves[pos+0].data + ctx.update leaves[pos+1].data + pos.inc 2 leaves[next] = ctx.finish() inc next + if pos < len: + leaves[next] = leaves[pos] + inc next len = next - # TODO: BLAKE2 tree finalization flags -proc blobHash*(s: string): BlobId = - doAssert(s.len <= blobLeafSize) +func blobHash*(s: string): BlobId = var - ctx: Blake2b256 - leaves: array[1, BlobId] - ctx.init do (params: var Blake2bParams): - params.fanout = 2 - params.depth = 255 - params.leafLength = blobLeafSize - params.nodeOffset = 0 - if s.len > 0: - ctx.update(unsafeAddr s[0], s.len) - leaves[0] = finish ctx + ctx: TigerState + leaves = newSeqOfCap[BlobId](leafCount s.len) + off: int + while true: + init ctx + ctx.update [0'u8] + let n = min(blobLeafSize, s.len - off) + if 0 < n: + ctx.update(unsafeAddr s[off], n) + off.inc n + leaves.add(finish ctx) + if off == s.len: break compressTree(leaves) leaves[0] @@ -651,12 +619,15 @@ proc commit*(store: BlobStore; bs: BlobSet): Future[BlobSet] {.async.} = type NullIngestStream = ref NullIngestStreamObj NullIngestStreamObj = object of IngestStreamObj - ctx: Blake2b256 + ctx: TigerState leaves: seq[BlobId] - pos, nodeOffset: BiggestInt + pos: BiggestInt proc nullBlobClose(s: BlobStream) = discard +proc nullBlobSize(s: BlobStream): BiggestInt = + discard + proc setPosNull(s: BlobStream; pos: BiggestInt) = discard proc getPosNull(s: BlobStream): BiggestInt = discard @@ -667,13 +638,15 @@ proc nullBlobRead(s: BlobStream; buffer: pointer; len: Natural): Future[int] = proc nullOpenBlobStream(s: BlobStore; id: BlobId; size: BiggestInt; kind: BlobKind): BlobStream = BlobStream( closeImpl: nullBlobClose, + sizeImpl: nullBlobSize, setPosImpl: setPosNull, getPosImpl: getPosNull, readImpl: nullBlobRead) proc nullFinish(s: IngestStream): Future[tuple[id: BlobId, size: BiggestInt]] = var s = NullIngestStream(s) - s.leaves.add finish(s.ctx) + if s.pos == 0 or s.pos mod blobLeafSize != 0: + s.leaves.add finish(s.ctx) compressTree(s.leaves) var pair: tuple[id: BlobId, size: BiggestInt] pair.id = s.leaves[0] @@ -681,34 +654,39 @@ proc nullFinish(s: IngestStream): Future[tuple[id: BlobId, size: BiggestInt]] = result = newFuture[tuple[id: BlobId, size: BiggestInt]]() complete result, pair -proc nullIngest(s: IngestStream; buf: pointer; len: Natural): Future[void] = - var +proc appendLeaf(s: NullIngestStream) = + s.leaves.add(finish s.ctx) + init s.ctx + s.ctx.update [0'u8] + +proc nullIngest(s: IngestStream; data: pointer; size: Natural): Future[void] = + let s = NullIngestStream(s) - off = 0 - buf = cast[ptr array[blobLeafSize, byte]](buf) - while off < len: - var n = min(blobLeafSize, len-off) - let leafOff = int(s.pos and blobLeafSizeMask) - if leafOff == 0: - if s.pos > 0: - s.leaves.add finish(s.ctx) - s.ctx.init do (params: var Blake2bParams): - params.fanout = 2 - params.depth = 255 - params.leafLength = blobLeafSize - params.nodeOffset = s.nodeOffset - inc s.nodeOffset - else: - n = min(n, blobLeafSize-leafOff) - s.ctx.update(buf[off].addr, n) - off.inc n - s.pos.inc n + buf = cast[ptr UncheckedArray[byte]](data) + var dataOff: int + let leafOff = s.pos.int mod blobLeafSize + if leafOff != 0: + let leafFill = min(blobLeafSize - leafOff, size) + s.ctx.update(buf[0].addr, leafFill) + dataOff.inc leafFill + if leafFill < size: + appendLeaf s + while dataOff+blobLeafSize <= size: + s.ctx.update(buf[dataOff].addr, blobLeafSize) + dataOff.inc blobLeafSize + appendLeaf s + if dataOff != size: + s.ctx.update(buf[dataOff].addr, size - dataOff) + s.pos.inc size result = newFuture[void]() complete result proc nullOpenIngestStream(s: BlobStore; size: BiggestInt; kind: BlobKind): IngestStream = - NullIngestStream( + let s = NullIngestStream( finishImpl: nullFinish, ingestImpl: nullIngest, leaves: newSeq[BlobId]()) + result = s + init s.ctx + s.ctx.update [0'u8] proc newNullStore*(): BlobStore = BlobStore( diff --git a/src/blobsets/filestores.nim b/src/blobsets/filestores.nim index e711528..8b08f29 100644 --- a/src/blobsets/filestores.nim +++ b/src/blobsets/filestores.nim @@ -1,9 +1,7 @@ import ../blobsets - +import tiger import std/asyncfile, std/asyncdispatch, std/os -import ./priv/nimcrypto/blake2 - proc ingestFile*(store: BlobStore; path: string): Future[tuple[id: BlobId, size: BiggestInt]] {.async.} = ## Ingest a file and return blob metadata. let @@ -13,7 +11,7 @@ proc ingestFile*(store: BlobStore; path: string): Future[tuple[id: BlobId, size: close file let stream = store.openIngestStream(fileSize, dataBlob) if fileSize > 0: - var buf = newString(min(blobLeafSize, fileSize)) + var buf = newString(min(8 shl 10, fileSize)) while true: let n = await file.readBuffer(buf[0].addr, buf.len) if n == 0: break @@ -28,7 +26,7 @@ type FsIngestStream = ref FsIngestStreamObj FsIngestStreamObj = object of IngestStreamObj - ctx: Blake2b256 + ctx: TigerState leaves: seq[BlobId] path: string file: AsyncFile @@ -43,6 +41,10 @@ proc fsBlobClose(s: BlobStream) = var s = FsBlobStream(s) close s.file +proc fsBlobSize(s: BlobStream): BiggestInt = + var s = FsBlobStream(s) + s.file.getFileSize.BiggestInt + proc setPosFs(s: BlobStream; pos: BiggestInt) = var s = FsBlobStream(s) s.file.setFilePos (int64)pos @@ -59,10 +61,11 @@ proc fsOpenBlobStream(s: BlobStore; id: BlobId; size: BiggestInt; kind: BlobKind var fs = FileStore(s) try: let - path = fs.root / $kind / id.toHex + path = fs.root / $kind / id.toBase32 file = openAsync(path, fmRead) result = FsBlobStream( closeImpl: fsBlobClose, + sizeImpl: fsBlobSize, setPosImpl: setPosFs, getPosImpl: getPosFs, readImpl: fsBlobRead, @@ -76,11 +79,12 @@ proc fsFinish(s: IngestStream): Future[tuple[id: BlobId, size: BiggestInt]] = s = FsIngestStream(s) pair: tuple[id: BlobId, size: BiggestInt] close s.file - s.leaves.add finish(s.ctx) + if s.pos == 0 or s.pos mod blobLeafSize != 0: + s.leaves.add finish(s.ctx) compressTree(s.leaves) pair.id = s.leaves[0] pair.size = s.pos - let finalPath = s.path.parentDir / pair.id.toHex + let finalPath = s.path.parentDir / pair.id.toBase32 if fileExists finalPath: removeFile s.path else: @@ -88,29 +92,31 @@ proc fsFinish(s: IngestStream): Future[tuple[id: BlobId, size: BiggestInt]] = result = newFuture[tuple[id: BlobId, size: BiggestInt]]() complete result, pair -proc fsIngest(s: IngestStream; buf: pointer; len: Natural) {.async.} = - var +proc appendLeaf(s: FsIngestStream) = + s.leaves.add(finish s.ctx) + init s.ctx + s.ctx.update [0'u8] + +proc fsIngest(s: IngestStream; data: pointer; size: Natural): Future[void] = + let s = FsIngestStream(s) - off = 0 - buf = cast[ptr array[blobLeafSize, byte]](buf) - while off < len: - var n = min(blobLeafSize, len-off) - let leafOff = int(s.pos and blobLeafSizeMask) - if leafOff == 0: - if s.pos > 0: - s.leaves.add finish(s.ctx) - s.ctx.init do (params: var Blake2bParams): - params.fanout = 2 - params.depth = 255 - params.leafLength = blobLeafSize - params.nodeOffset = s.nodeOffset - inc s.nodeOffset - else: - n = min(n, blobLeafSize-leafOff) - s.ctx.update(buf[off].addr, n) - await s.file.writeBuffer(buf[off].addr, n) - off.inc n - s.pos.inc n + buf = cast[ptr UncheckedArray[byte]](data) + result = s.file.writeBuffer(data, size) + var dataOff: int + let leafOff = s.pos.int mod blobLeafSize + if leafOff != 0: + let leafFill = min(blobLeafSize - leafOff, size) + s.ctx.update(buf[0].addr, leafFill) + dataOff.inc leafFill + if leafFill < size: + appendLeaf s + while dataOff+blobLeafSize <= size: + s.ctx.update(buf[dataOff].addr, blobLeafSize) + dataOff.inc blobLeafSize + appendLeaf s + if dataOff != size: + s.ctx.update(buf[dataOff].addr, size - dataOff) + s.pos.inc size proc fsOpenIngestStream(s: BlobStore; size: BiggestInt; kind: BlobKind): IngestStream = var fs = FileStore(s) @@ -127,12 +133,14 @@ proc fsOpenIngestStream(s: BlobStore; size: BiggestInt; kind: BlobKind): IngestS stream.leaves = newSeqOfCap[BlobId](leafCount size) else: stream.leaves = newSeq[BlobId]() + init stream.ctx + stream.ctx.update [0'u8] stream proc fsContains(s: BlobStore; id: BlobId; kind: BlobKind): Future[bool] = var fs = FileStore(s) result = newFuture[bool]("blobsets.filestores.fsContains") - let path = fs.root / $kind / id.toHex + let path = fs.root / $kind / id.toBase32 try: close(openAsync(path, fmRead)) result.complete(true) diff --git a/src/blobsets/fsnodes.nim b/src/blobsets/fsnodes.nim deleted file mode 100644 index dfc0205..0000000 --- a/src/blobsets/fsnodes.nim +++ /dev/null @@ -1,377 +0,0 @@ -import strutils, streams, tables, cbor, os, math, asyncfile, asyncdispatch - -import ../blobsets, ./stores - -type EntryKey = enum - typeKey = 1, - dataKey = 2, - sizeKey = 3 - -type FsType* = enum - fsFileList = 0, - fsDirChunk = 1, - fsFileChunk = 2, - -type FsKind* = enum - fileNode, - dirNode, - shallowDirChunk, - shallowFileList, - -type - FileLink* = object - cid*: Cid - size*: int - - FsNode* = ref object - cid: Cid - case kind*: FsKind - of fileNode: - links*: seq[FileLink] - of dirNode: - entries: OrderedTable[string, FsNode] - of shallowFileList, shallowDirChunk: - discard - size: BiggestInt - -proc isRaw*(file: FsNode): bool = - (file.kind == fileNode) and (file.links.len == 0) - -proc cid*(u: FsNode): Cid = - assert u.cid.isValid - u.cid - -proc isFile*(u: FsNode): bool = u.kind in { fileNode, shallowFileList } -proc isDir*(u: FsNode): bool = u.kind in { dirNode, shallowDirChunk } - -proc size*(u: FsNode): BiggestInt = - if u.kind == dirNode: u.entries.len.BiggestInt - else: u.size - -proc newFsRoot*(): FsNode = - FsNode( - kind: dirNode, - entries: initOrderedTable[string, FsNode](8)) - -proc newUnixfsFile*(): FsNode = - FsNode(kind: fileNode) - -proc newUnixfsDir*(cid: Cid): FsNode = - FsNode(cid: cid, kind: dirNode) - -proc add*(root: var FsNode; name: string; node: FsNode) = - root.entries[name] = node - -proc addDir*(root: var FsNode; name: string; cid: Cid) {.deprecated.} = - assert cid.isValid - root.add name, FsNode(kind: dirNode, cid: cid) - -proc addFile*(root: var FsNode; name: string; cid: Cid; size: BiggestInt) {.deprecated.} = - assert cid.isValid - root.add name, FsNode(kind: fileNode, cid: cid, size: size) - -proc del*(dir: var FsNode; name: string) = - dir.entries.del name - -const - DirTag* = 0xda3c80 ## CBOR tag for UnixFS directories - FileTag* = 0xda3c81 ## CBOR tag for UnixFS files - -proc isUnixfs*(bin: string): bool = - ## Check if a string contains a UnixFS node - ## in CBOR form. - var - s = newStringStream bin - c: CborParser - try: - c.open s - c.next - if c.kind == CborEventKind.cborTag: - result = c.tag == DirTag or c.tag == FileTag - except ValueError: discard - close s - -proc toCbor*(u: FsNode): CborNode = - case u.kind - of fileNode: - let array = newCborArray() - array.seq.setLen u.links.len - for i in 0..u.links.high: - let L = newCborMap() - # typeEntry is reserved but not in use - L[dataKey.int] = u.links[i].cid.newCborBytes - L[sizeKey.int] = u.links[i].size.newCborInt - array.seq[i] = L - result = newCborTag(FileTag, array) - of dirNode: - let map = newCborMap() - for name, node in u.entries: - var entry = newCborMap() - case node.kind - of fileNode, shallowFileList: - if node.isRaw: - entry[typeKey.int] = fsFileChunk.int.newCborInt - else: - entry[typeKey.int] = fsFileList.int.newCborInt - entry[dataKey.int] = node.cid.newCborBytes - entry[sizeKey.int] = node.size.newCborInt - of dirNode: - entry[typeKey.int] = fsDirChunk.int.newCborInt - entry[dataKey.int] = node.cid.newCborBytes - entry[sizeKey.int] = node.entries.len.newCborInt - of shallowDirChunk: - entry[typeKey.int] = fsDirChunk.int.newCborInt - entry[dataKey.int] = node.cid.newCborBytes - entry[sizeKey.int] = node.size.int.newCborInt - map[name] = entry - # TODO: the CBOR maps must be sorted - result = newCborTag(DirTag, map) - else: - raiseAssert "shallow FsNodes can not be encoded" - -template parseAssert(cond: bool; msg = "") = - if not cond: raise newException( - ValueError, - if msg == "": "invalid UnixFS CBOR" else: "invalid UnixFS CBOR, " & msg) - -proc parseFs*(raw: string; cid: Cid): FsNode = - ## Parse a string containing CBOR data into a FsNode. - new result - result.cid = cid - var - c: CborParser - buf = "" - open(c, newStringStream(raw)) - next c - parseAssert(c.kind == CborEventKind.cborTag, "data not tagged") - let tag = c.tag - if tag == FileTag: - result.kind = fileNode - next c - parseAssert(c.kind == CborEventKind.cborArray, "file data not an array") - let nLinks = c.arrayLen - result.links = newSeq[FileLink](nLinks) - for i in 0.. 1, raw) - let entry = new FsNode - result.entries[buf] = entry - for i in 1 .. nAttrs: - next c - parseAssert(c.kind == CborEventKind.cborPositive) - case c.readInt.EntryKey - of typeKey: - next c - case c.readInt.FsType - of fsFileList: entry.kind = shallowFileList - of fsDirChunk: entry.kind = shallowDirChunk - of fsFileChunk: - entry.kind = fileNode - entry.links = newSeq[FileLink](0) - of dataKey: - next c - c.readBytes buf - entry.cid.take buf - of sizeKey: - next c - entry.size = c.readInt - else: - parseAssert(false, raw) - next c - parseAssert(c.kind == cborEof, "trailing data") - -proc toStream*(node: FsNode; s: Stream) = - let c = node.toCbor() - c.toStream s - -iterator items*(dir: FsNode): (string, FsNode) = - assert(dir.kind == dirNode) - for k, v in dir.entries.pairs: - yield (k, v) - -proc containsFile*(dir: FsNode; name: string): bool = - doAssert(dir.kind == dirNode) - dir.entries.contains name - -proc `[]`*(dir: FsNode; name: string): FsNode = - if dir.kind == dirNode: - result = dir.entries.getOrDefault name - -proc `[]`*(dir: FsNode; index: int): (string, FsNode) = - result[0] = "" - if dir.kind == dirNode: - var i = 0 - for name, node in dir.entries.pairs: - if i == index: - result = (name, node) - break - inc i - -proc lookupFile*(dir: FsNode; name: string): tuple[cid: Cid, size: BiggestInt] = - doAssert(dir.kind == dirNode) - let f = dir.entries[name] - if f.kind == fileNode: - result.cid = f.cid - result.size = f.size - -proc addFile*(store: BlobStore; path: string): FsNode = - ## Add a file to the store and a FsNode. - let - file = openAsync(path, fmRead) - fileSize = file.getFileSize - u = newUnixfsFile() - u.links = newSeqOfCap[FileLink](1) - var - buf = newString(min(maxChunKSize, fileSize)) - pos = 0 - let shortLen = fileSize mod maxChunKSize - if 0 < shortLen: - buf.setLen shortLen - # put the short chunck first - while true: - let n = waitFor file.readBuffer(buf[0].addr, buf.len) - buf.setLen n - let cid = store.put(buf) - u.links.add FileLink(cid: cid, size: buf.len) - u.size.inc buf.len - pos.inc n - if pos >= fileSize: break - buf.setLen maxChunkSize - close file - if u.size == 0: - # return the CID for a raw nothing - u.cid = dagHash("") - else: - if u.links.len == 1: - # take a shortcut use the raw chunk CID - u.cid = u.links[0].cid - u.links.setLen 0 - else: - u.cid = store.putDag(u.toCbor) - result = u - -proc addDir*(store: BlobStore; dirPath: string): FsNode = - var dRoot = newFsRoot() - for kind, path in walkDir dirPath: - var child: FsNode - case kind - of pcFile, pcLinkToFile: - child = store.addFile path - of pcDir, pcLinkToDir: - child = store.addDir(path) - else: continue - dRoot.add path.extractFilename, child - let - dag = dRoot.toCbor - cid = store.putDag(dag) - result = newUnixfsDir(cid) - -proc open*(store: BlobStore; cid: Cid): FsNode = - assert cid.isValid - let raw = store.get(cid) - result = parseFs(raw, cid) - -proc openDir*(store: BlobStore; cid: Cid): FsNode = - assert cid.isValid - var raw = "" - try: store.get(cid, raw) - except MissingChunk: raiseMissing cid - # this sucks - result = parseFs(raw, cid) - assert(result.kind == dirNode) - -proc walk*(store: BlobStore; dir: FsNode; path: string; cache = true): FsNode = - ## Walk a path down a root. - assert(dir.kind == dirNode) - result = dir - var raw = "" - for name in split(path, DirSep): - if name == "": continue - if result.kind == fileNode: - result = nil - break - var next = result[name] - if next.isNil: - result = nil - break - if (next.kind in {shallowFileList, shallowDirChunk}): - store.get(next.cid, raw) - next = parseFs(raw, next.cid) - if cache: - result.entries[name] = next - result = next - -#[ -iterator fileChunks*(store: BlobStore; file: FsNode): string = - ## Iterate over the links in a file and return futures for link data. - if file.cid.isRaw: - yield store.get(file.cid) - else: - var - i = 0 - chunk = "" - while i < file.links.len: - store.get(file.links[i].cid, chunk) - yield chunk - inc i -]# - -proc readBuffer*(store: BlobStore; file: FsNode; pos: BiggestInt; - buf: pointer; size: int): int = - ## Read a UnixFS file into a buffer. May return zero for any failure. - assert(pos > -1) - var - filePos = 0 - chunk = "" - if pos < file.size: - if file.isRaw: - let pos = pos.int - store.get(file.cid, chunk) - if pos < chunk.high: - copyMem(buf, chunk[pos].addr, min(chunk.len - pos, size)) - result = size - else: - for i in 0..file.links.high: - let linkSize = file.links[i].size - if filePos <= pos and pos < filePos+linkSize: - store.get(file.links[i].cid, chunk) - let - chunkPos = int(pos - filePos) - n = min(chunk.len-chunkPos, size) - copyMem(buf, chunk[chunkPos].addr, n) - result = n - break - filePos.inc linkSize diff --git a/src/blobsets/httpservers.nim b/src/blobsets/httpservers.nim index b349899..29ddedb 100644 --- a/src/blobsets/httpservers.nim +++ b/src/blobsets/httpservers.nim @@ -12,7 +12,7 @@ type # TODO: tables must be purged periodically rng: Rand -proc newHttpStoreServer*(backend: BlobStore; seed = 0'i64): HttpStoreServer = +proc newHttpStoreServer*(backend: BlobStore; seed = 1'i64): HttpStoreServer = ## Create a new HTTP server for a given store. randomize() HttpStoreServer( @@ -62,8 +62,8 @@ proc get(hss: HttpStoreServer; req: Request) {.async.} = if range != "": let (startPos, endPos) = parseRange range - pos = startPos - len = endPos - startPos + pos = startPos + len = endPos - startPos stream.pos = pos var body = newString(len) len = await stream.read(body[0].addr, len) diff --git a/src/blobsets/httpstores.nim b/src/blobsets/httpstores.nim index b860d7c..a28d3ff 100644 --- a/src/blobsets/httpstores.nim +++ b/src/blobsets/httpstores.nim @@ -1,5 +1,6 @@ -import std/asyncdispatch, std/httpclient, std/strutils, std/uri import ../blobsets +import tiger +import std/asyncdispatch, std/httpclient, std/strutils, std/uri type HttpBlobStream = ref HttpBlobStreamObj @@ -12,7 +13,7 @@ type HttpIngestStreamObj = object of IngestStreamObj client: AsyncHttpClient url: string - ctx: Blake2b256 + ctx: TigerState leaves: seq[BlobId] leaf: string buffOff: int @@ -27,6 +28,10 @@ type proc httpBlobClose(s: BlobStream) = discard +proc httpBlobSize(s: BlobStream): BiggestInt = + var s = HttpBlobStream(s) + discard + proc setPosHttp(s: BlobStream; pos: BiggestInt) = var s = (HttpBlobStream)s s.rangePos = pos @@ -52,6 +57,7 @@ proc httpOpenBlobStream(store: BlobStore; id: BlobId; size: BiggestInt; kind: Bl let stream = HttpBlobStream( client: store.client, closeImpl: httpBlobClose, + sizeImpl: httpBlobSize, setPosImpl: setPosHttp, getPosImpl: getPosHttp, readImpl: httpBlobRead, diff --git a/src/blobsets/priv/blake2.nim b/src/blobsets/priv/blake2.nim deleted file mode 100644 index 45cbee8..0000000 --- a/src/blobsets/priv/blake2.nim +++ /dev/null @@ -1,190 +0,0 @@ -import std/bitops, std/endians - -type - Blake2b* = object - hash: array[8, uint64] - offset: array[2, uint64] - buffer: array[128, uint8] - buffer_idx: uint8 - hash_size: uint8 - - Blake2bParams* = object - b: array[64, byte] - Blake2sParams* = object - b: array[32, byte] - Blake2Params* = Blake2bParams | Blake2sParams - -proc params(c: var Blake2b): ptr Blake2bParams = - cast[ptr Blake2bParams](c.hash.addr) - -proc `digestLen=`*(p: ptr Blake2bParams; x: range[1..64]) = - p.b[0] = (uint8)x -proc `digestLen=`*(p: ptr Blake2sParams; x: range[1..32]) = - p.b[0] = (uint8)x -proc `keyLen=`*(p: ptr Blake2bParams; x: range[0..64]) = - p.b[1] = (uint8)x -proc `keyLen=`*(p: ptr Blake2sParams; x: range[0..32]) = - p.b[1] = (uint8)x -proc `fanout=`*(p: ptr Blake2Params; x: Natural) = - p.b[2] = (uint8)x -proc `depth=`*(p: ptr Blake2Params; x: Natural) = - p.b[3] = (uint8)x - -proc `leafLength=`*(p: ptr Blake2Params; x: Natural) = - var x = x; littleEndian32(p.b[4].addr, x.addr) - -proc `nodeOffset=`*(p: ptr Blake2bParams; x: Natural) = - var x = x; littleEndian64(p.b[8].addr, x.addr) -proc `nodeOffset=`*(p: ptr Blake2sParams; x: Natural) = - var tmp: int64 - littleEndian64(tmp.addr, p.b[8].addr) - tmp = (tmp and 0xffffffff) or (x shl 32) - littleEndian64(p.b[8].addr, tmp.addr) - -proc `nodeDepth=`*(p: ptr Blake2bParams; x: Natural) = - p.b[16] = (uint8)x -proc `nodeDepth=`*(p: ptr Blake2sParams; x: Natural) = - p.b[14] = (uint8)x - -proc `innerLength=`*(p: ptr Blake2bParams; x: Natural) = - p.b[17] = (uint8)x -proc `innerLength=`*(p: ptr Blake2sParams; x: Natural) = - p.b[15] = (uint8)x - -proc `salt=`*(p: ptr Blake2bParams; salt: pointer; len: Natural) = - copyMem(p.b[32].addr, salt, min(len, 16)) -proc `salt=`*(p: ptr Blake2sParams; salt: pointer; len: Natural) = - copyMem(p.b[16].addr, salt, min(len, 8)) - -proc `personal=`*(p: ptr Blake2bParams; salt: pointer; len: Natural) = - copyMem(p.b[48].addr, salt, min(len, 16)) -proc `personal=`*(p: ptr Blake2sParams; salt: pointer; len: Natural) = - copyMem(p.b[24].addr, salt, min(len, 8)) - -proc init(p: ptr Blake2Params) = - when p is Blake2bParams: - p.digestLen = 64 - else: - p.digestLen = 32 - p.fanout = 1 - p.depth = 1 - -const Blake2bIV = - [ 0x6a09e667f3bcc908'u64, 0xbb67ae8584caa73b'u64, - 0x3c6ef372fe94f82b'u64, 0xa54ff53a5f1d36f1'u64, - 0x510e527fade682d1'u64, 0x9b05688c2b3e6c1f'u64, - 0x1f83d9abfb41bd6b'u64, 0x5be0cd19137e2179'u64 ] - -const Sigma = [ - [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ], - [ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ], - [ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ], - [ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ], - [ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ], - [ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ], - [ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ], - [ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ], - [ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 ], - [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ], - [ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ] ] - -proc inc(a: var array[2, uint64], b: uint8) = - a[0] = a[0] + b - if (a[0] < b): inc(a[1]) - -proc padding(a: var array[128, uint8], b: uint8) = - for i in b..127: a[i] = 0 - -proc G (v: var array[16, uint64], - a,b,c,d: int, x,y: uint64) - {.inline.} = - v[a] = v[a] + v[b] + x - v[d] = rotateRightBits(v[d] xor v[a], 32) - v[c] = v[c] + v[d] - v[b] = rotateRightBits(v[b] xor v[c], 24) - v[a] = v[a] + v[b] + y - v[d] = rotateRightBits(v[d] xor v[a], 16) - v[c] = v[c] + v[d] - v[b] = rotateRightBits(v[b] xor v[c], 63) - -proc compress(c: var Blake2b, last: int = 0) = - var input, v: array[16, uint64] - for i in 0..15: - input[i] = cast[ptr uint64](addr(c.buffer[i*8]))[] - for i in 0..7: - v[i] = c.hash[i] - v[i+8] = Blake2bIV[i] - v[12] = v[12] xor c.offset[0] - v[13] = v[13] xor c.offset[1] - if (last == 1): v[14] = not(v[14]) - for i in 0..11: - G(v, 0, 4, 8, 12, input[Sigma[i][0]], input[Sigma[i][1]]) - G(v, 1, 5, 9, 13, input[Sigma[i][2]], input[Sigma[i][3]]) - G(v, 2, 6, 10, 14, input[Sigma[i][4]], input[Sigma[i][5]]) - G(v, 3, 7, 11, 15, input[Sigma[i][6]], input[Sigma[i][7]]) - G(v, 0, 5, 10, 15, input[Sigma[i][8]], input[Sigma[i][9]]) - G(v, 1, 6, 11, 12, input[Sigma[i][10]], input[Sigma[i][11]]) - G(v, 2, 7, 8, 13, input[Sigma[i][12]], input[Sigma[i][13]]) - G(v, 3, 4, 9, 14, input[Sigma[i][14]], input[Sigma[i][15]]) - for i in 0..7: - c.hash[i] = c.hash[i] xor v[i] xor v[i+8] - c.buffer_idx = 0 - -{.push boundChecks: off.} -proc update*(c: var Blake2b, buf: pointer, data_size: int) = - var data = cast[ptr array[0, uint8]](buf) - for i in 0.. 0: - update(result, key, key_size) - padding(result.buffer, result.buffer_idx) - result.buffer_idx = 128 - -proc initBlake2b*(customize: proc(params: ptr Blake2bParams)): Blake2b = - let p = result.params - init(p) - customize(p) - result.hash_size = p.b[0] - for i in 0..7: - result.hash[0] = result.hash[0] xor Blake2bIV[i] - -proc finish*(c: var Blake2b): seq[uint8] = - result = newSeq[uint8](c.hash_size) - inc(c.offset, c.buffer_idx) - padding(c.buffer, c.buffer_idx) - compress(c, 1) - for i in 0'u8... -## Copyright (c) 2016 Thomas Pornin -## -## Tests made according to official test vectors (Appendix F) -## http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf -## GCM tests made according official test vectors (Appendix B) -## https://pdfs.semanticscholar.org/114a/4222c53f1a6879f1a77f1bae2fc0f8f55348.pdf -## and OpenSSL vectors -## https://github.com/majek/openssl/blob/master/crypto/evp/evptests.txt -import utils - -{.deadCodeElim:on.} - -const - MaxBlockSize = 256 - MaxBlockBytesSize = MaxBlockSize shr 3 - -type - ECB*[T] = object - ## ECB (Electronic Code Book) context object - cipher: T - tmp: array[MaxBlockBytesSize, byte] - - CBC*[T] = object - ## CBC (Cipher Block Chaining) context object - cipher: T - iv: array[MaxBlockBytesSize, byte] - tmp: array[MaxBlockBytesSize, byte] - - OFB*[T] = object - ## OFB (Output FeedBack) context object - cipher: T - iv: array[MaxBlockBytesSize, byte] - - CFB*[T] = object - ## CFB (Cipher FeedBack) context object - cipher: T - iv: array[MaxBlockBytesSize, byte] - - CTR*[T] = object - ## CTR (Counter) context object - cipher: T - iv: array[MaxBlockBytesSize, byte] - ecount: array[MaxBlockBytesSize, byte] - num: uint - - GCM*[T] = object - ## GCM (Galois/Counter Mode) context object - cipher: T - h: array[16, byte] - y: array[16, byte] - basectr: array[16, byte] - buf: array[16, byte] - aadlen: uint64 - datalen: uint64 - -## ECB (Electronic Code Book) Mode - -template sizeBlock*[T](ctx: ECB[T]): int = - ## Size of ``ECB[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: ECB[T]): int = - ## Size of ``ECB[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc init*[T](ctx: var ECB[T], key: ptr byte) = - ## Initialize ``ECB[T]`` with encryption key ``key``. - ## - ## Note! Size of data pointed by ``key`` must be at least ``ctx.sizeKey`` - ## octets (bytes). - mixin init - assert(not isNil(key)) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, key) - -proc init*[T](ctx: var ECB[T], key: openarray[byte]) {.inline.} = - ## Initialize ``ECB[T]`` with encryption key ``key``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key``. - ## - ## Length of ``key`` must be at least ``ECB[T].sizeKey()`` octets (bytes). - ## - ## You can see examples of usage ECB mode here ``examples/ecb.nim``. - assert(len(key) >= ctx.sizeKey()) - init(ctx, unsafeAddr key[0]) - -proc init*[T](ctx: var ECB[T], key: openarray[char]) {.inline.} = - ## Initialize ``ECB[T]`` with encryption key ``key``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key``. - ## - ## Length of ``key`` must be at least ``ECB[T].sizeKey()`` octets (bytes). - ## - ## You can see examples of usage ECB mode here ``examples/ecb.nim``. - assert(len(key) >= ctx.sizeKey()) - init(ctx, cast[ptr byte](unsafeAddr key[0])) - -proc clear*[T](ctx: var ECB[T]) {.inline.} = - ## Clear ``ECB[T]`` context ``ctx``. - burnMem(ctx) - -proc encrypt*[T](ctx: var ECB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``ECB[T]`` encryption of plain data pointed by ``inp`` of length - ## ``length`` and store encrypted data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length mod uint(ctx.sizeBlock) == 0) - - var blen = uint(ctx.sizeBlock) - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var tp = cast[ptr UncheckedArray[byte]](addr ctx.tmp[0]) - - var i = length - while i != 0: - if i < blen: - copyMem(tp, ip, i) - ctx.cipher.encrypt(cast[ptr byte](tp), cast[ptr byte](op)) - break - ctx.cipher.encrypt(cast[ptr byte](ip), cast[ptr byte](op)) - i = i - blen - ip = cast[ptr UncheckedArray[byte]](cast[uint](ip) + blen) - op = cast[ptr UncheckedArray[byte]](cast[uint](op) + blen) - result = length - -proc decrypt*[T](ctx: var ECB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``ECB[T]`` decryption of encrypted data pointed by ``inp`` of - ## length ``length`` and store plain data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin decrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length mod uint(ctx.sizeBlock) == 0) - - var blen = uint(ctx.sizeBlock) - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var i = length - while i != 0: - ctx.cipher.decrypt(cast[ptr byte](ip), cast[ptr byte](op)) - i = i - blen - ip = cast[ptr UncheckedArray[byte]](cast[uint](ip) + blen) - op = cast[ptr UncheckedArray[byte]](cast[uint](op) + blen) - result = length - -proc encrypt*[T](ctx: var ECB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``ECB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc encrypt*[T](ctx: var ECB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``ECB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -proc decrypt*[T](ctx: var ECB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``ECB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc decrypt*[T](ctx: var ECB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``ECB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -## CBC (Cipher Block Chaining) Mode - -template sizeBlock*[T](ctx: CBC[T]): int = - ## Size of ``CBC[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: CBC[T]): int = - ## Size of ``CBC[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc init*[T](ctx: var CBC[T], key: ptr byte, iv: ptr byte) = - ## Initialize ``CBC[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## Note! Size of encryption key pointed by ``key`` must be at least - ## ``ctx.sizeKey`` octets (bytes) and size of initial vector ``iv`` must be at - ## least ``ctx.sizeBlock`` octets (bytes). - ## - ## You can see examples of usage CBC mode here ``examples/cbc.nim``. - mixin init - assert(not isNil(key) and not isNil(iv)) - init(ctx.cipher, key) - assert(ctx.sizeBlock <= MaxBlockSize) - copyMem(addr ctx.iv[0], iv, ctx.sizeBlock) - -proc init*[T](ctx: var CBC[T], key: openarray[byte], iv: openarray[byte]) = - ## Initialize ``CBC[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` must be at least ``ctx.sizeBlock()`` octets (bytes) - ## - ## You can see examples of usage CBC mode here ``examples/cbc.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, unsafeAddr key[0]) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc init*[T](ctx: var CBC[T], key: openarray[char], iv: openarray[char]) = - ## Initialize ``CBC[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` must be at least ``ctx.sizeBlock()`` octets (bytes) - ## - ## You can see examples of usage CBC mode here ``examples/cbc.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, cast[ptr byte](unsafeAddr key[0])) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc clear*[T](ctx: var CBC[T]) {.inline.} = - ## Clear ``CBC[T]`` context ``ctx``. - burnMem(ctx) - -proc encrypt*[T](ctx: var CBC[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``CBC[T]`` encryption of plain data pointed by ``inp`` of length - ## ``length`` and store encrypted data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - - var blen = uint(ctx.sizeBlock) - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - - var i = length - while i != 0: - var n = 0'u - while (n < blen) and (n < length): - op[n] = ip[n] xor cp[n] - inc(n) - while n < blen: - op[n] = cp[n] - inc(n) - ctx.cipher.encrypt(cast[ptr byte](op), cast[ptr byte](op)) - cp = op - if i < blen: - break - i = i - blen - ip = cast[ptr UncheckedArray[byte]](cast[uint](ip) + blen) - op = cast[ptr UncheckedArray[byte]](cast[uint](op) + blen) - copyMem(addr ctx.iv[0], cp, blen) - result = length - -proc decrypt*[T](ctx: var CBC[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``CBC[T]`` decryption of encrypted data pointed by ``inp`` of - ## length ``length`` and store plain data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin decrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - - let blen = uint(ctx.sizeBlock) - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var tp = cast[ptr UncheckedArray[byte]](addr ctx.tmp[0]) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - - var i = length - while i != 0: - var n = 0'u - ctx.cipher.decrypt(cast[ptr byte](ip), cast[ptr byte](tp)) - while (n < blen) and (n < length): - var c = ip[n] - op[n] = tp[n] xor cp[n] - cp[n] = c - inc(n) - if i < blen: - while n < blen: - cp[n] = ip[n] - break - i = i - blen - ip = cast[ptr UncheckedArray[byte]](cast[uint](ip) + blen) - op = cast[ptr UncheckedArray[byte]](cast[uint](op) + blen) - result = length - -proc encrypt*[T](ctx: var CBC[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CBC[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc encrypt*[T](ctx: var CBC[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CBC[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -proc decrypt*[T](ctx: var CBC[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CBC[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc decrypt*[T](ctx: var CBC[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CBC[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -## CTR (Counter) Mode - -template sizeBlock*[T](ctx: CTR[T]): int = - ## Size of ``CTR[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: CTR[T]): int = - ## Size of ``CTR[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc inc128(counter: ptr UncheckedArray[byte]) = - var n = 16'u32 - var c = 1'u32 - while true: - dec(n) - c = c + counter[n] - counter[n] = cast[byte](c) - c = c shr 8 - if n == 0: - break - -proc inc128(counter: var array[16, byte]) = - var n = 16'u32 - var c = 1'u32 - while true: - dec(n) - c = c + counter[n] - counter[n] = cast[byte](c) - c = c shr 8 - if n == 0: - break - -proc inc256(counter: ptr UncheckedArray[byte]) = - var n = 32'u32 - var c = 1'u32 - while true: - dec(n) - c = c + counter[n] - counter[n] = cast[byte](c) - c = c shr 8 - if n == 0: - break - -proc init*[T](ctx: var CTR[T], key: ptr byte, iv: ptr byte) = - ## Initialize ``CTR[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## Note! Size of encryption key pointed by ``key`` must be at least - ## ``ctx.sizeKey`` octets (bytes) and size of initial vector ``iv`` must be at - ## least ``ctx.sizeBlock`` octets (bytes). - ## - ## You can see examples of usage CTR mode here ``examples/ctr.nim``. - mixin init - assert(not isNil(key) and not isNil(iv)) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, key) - copyMem(addr ctx.iv[0], iv, ctx.sizeBlock) - -proc init*[T](ctx: var CTR[T], key: openarray[byte], iv: openarray[byte]) = - ## Initialize ``CTR[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage CTR mode here ``examples/ctr.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, unsafeAddr key[0]) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc init*[T](ctx: var CTR[T], key: openarray[char], - iv: openarray[char]) {.inline.} = - ## Initialize ``CTR[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage CTR mode here ``examples/ctr.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, cast[ptr byte](unsafeAddr key[0])) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc clear*[T](ctx: var CTR[T]) {.inline.} = - ## Clear ``CTR[T]`` context ``ctx``. - burnMem(ctx) - -proc encrypt*[T](ctx: var CTR[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``CTR[T]`` encryption of plain data pointed by ``inp`` of length - ## ``length`` and store encrypted data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - assert(ctx.sizeBlock == (128 div 8) or ctx.sizeBlock == (256 div 8)) - var n = ctx.num - var i = 0'u - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - let mask = uint(ctx.sizeBlock) - - while i < length: - if n == 0: - ctx.cipher.encrypt(addr ctx.iv[0], addr ctx.ecount[0]) - if ctx.sizeBlock == (128 div 8): - inc128(cp) - elif ctx.sizeBlock == (256 div 8): - inc256(cp) - op[i] = cast[byte](ip[i] xor ctx.ecount[n]) - inc(i) - n = (n + 1) mod mask - - ctx.num = uint(n) - result = ctx.num - -proc decrypt*[T](ctx: var CTR[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable, inline.} = - ## Perform ``CTR[T]`` decryption of encrypted data pointed by ``inp`` of - ## length ``length`` and store decrypted data to ``oup``. ``oup`` must be able - ## to hold at least ``length`` octets (bytes) of data. - ## - ## Procedures returns number of processed octets (bytes). - mixin encrypt - result = encrypt(ctx, inp, oup, length) - -proc encrypt*[T](ctx: var CTR[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CTR[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc encrypt*[T](ctx: var CTR[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CTR[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -proc decrypt*[T](ctx: var CTR[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CTR[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc decrypt*[T](ctx: var CTR[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CTR[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -## OFB (Output Feedback) Mode - -template sizeBlock*[T](ctx: OFB[T]): int = - ## Size of ``OFB[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: OFB[T]): int = - ## Size of ``OFB[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc init*[T](ctx: var OFB[T], key: ptr byte, iv: ptr byte) = - ## Initialize ``OFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## Note! Size of encryption key pointed by ``key`` must be at least - ## ``ctx.sizeKey`` octets (bytes) and size of initial vector ``iv`` must be at - ## least ``ctx.sizeBlock`` octets (bytes). - ## - ## You can see examples of usage OFB mode here ``examples/ofb.nim``. - mixin init - assert(not isNil(key) and not isNil(iv)) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, key) - copyMem(addr ctx.iv[0], iv, ctx.sizeBlock) - -proc init*[T](ctx: var OFB[T], key: openarray[byte], iv: openarray[byte]) = - ## Initialize ``OFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage OFB mode here ``examples/ofb.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, unsafeAddr key[0]) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc init*[T](ctx: var OFB[T], key: openarray[char], iv: openarray[char]) = - ## Initialize ``OFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage OFB mode here ``examples/ofb.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, cast[ptr byte](unsafeAddr key[0])) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc clear*[T](ctx: var OFB[T]) {.inline.} = - ## Clear ``OFB[T]`` context ``ctx``. - burnMem(ctx) - -proc encrypt*[T](ctx: var OFB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``OFB[T]`` encryption of plain data pointed by ``inp`` of length - ## ``length`` and store encrypted data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - assert(ctx.sizeBlock == (128 div 8) or ctx.sizeBlock == (256 div 8)) - var n = 0 - var i = 0'u - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - let mask = ctx.sizeBlock - - while i < length: - if n == 0: - ctx.cipher.encrypt(cast[ptr byte](cp), cast[ptr byte](cp)) - op[i] = ip[i] xor cp[n] - inc(i) - n = (n + 1) mod mask - result = uint(n) - -proc decrypt*[T](ctx: var OFB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable, inline.} = - ## Perform ``OFB[T]`` decryption of encrypted data pointed by ``inp`` of - ## length ``length`` and store plain data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - result = encrypt(ctx, inp, oup, length) - -proc encrypt*[T](ctx: var OFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``OFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc encrypt*[T](ctx: var OFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``OFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -proc decrypt*[T](ctx: var OFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``OFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc decrypt*[T](ctx: var OFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``OFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -## CFB (Cipher Feedback) Mode - -template sizeBlock*[T](ctx: CFB[T]): int = - ## Size of ``CFB[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: CFB[T]): int = - ## Size of ``CFB[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc init*[T](ctx: var CFB[T], key: ptr byte, iv: ptr byte) = - ## Initialize ``CFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## Note! Size of encryption key pointed by ``key`` must be at least - ## ``ctx.sizeKey`` octets (bytes) and size of initial vector ``iv`` must be at - ## least ``ctx.sizeBlock`` octets (bytes). - ## - ## You can see examples of usage CFB mode here ``examples/cfb.nim``. - mixin init - assert(not isNil(key) and not isNil(iv)) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, key) - copyMem(addr ctx.iv[0], iv, ctx.sizeBlock) - -proc init*[T](ctx: var CFB[T], key: openarray[byte], iv: openarray[byte]) = - ## Initialize ``CFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage CFB mode here ``examples/cfb.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, unsafeAddr key[0]) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc init*[T](ctx: var CFB[T], key: openarray[char], iv: openarray[char]) = - ## Initialize ``CFB[T]`` with encryption key ``key`` and initial vector (IV) - ## ``iv``. - ## - ## This procedure will not perform any additional padding for encryption - ## key ``key`` and initial vector ``iv``. - ## - ## Length of ``key`` array must be at least ``ctx.sizeKey()`` octets (bytes). - ## Length of ``iv`` array must be at least ``ctx.sizeBlock()`` octets (bytes). - ## - ## You can see examples of usage CFB mode here ``examples/cfb.nim``. - mixin init - assert(len(iv) >= ctx.sizeBlock) - assert(len(key) >= ctx.sizeKey) - assert(ctx.sizeBlock <= MaxBlockSize) - init(ctx.cipher, cast[ptr byte](unsafeAddr key[0])) - copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock) - -proc clear*[T](ctx: var CFB[T]) {.inline.} = - ## Clear ``CFB[T]`` context ``ctx``. - burnMem(ctx) - -proc encrypt*[T](ctx: var CFB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``CFB[T]`` encryption of plain data pointed by ``inp`` of length - ## ``length`` and store encrypted data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - var n = 0 - var i = 0'u - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - let mask = ctx.sizeBlock - - while i < length: - if n == 0: - ctx.cipher.encrypt(cast[ptr byte](cp), cast[ptr byte](cp)) - cp[n] = cp[n] xor ip[i] - op[i] = cp[n] - inc(i) - n = (n + 1) mod mask - result = uint(n) - -proc decrypt*[T](ctx: var CFB[T], inp: ptr byte, oup: ptr byte, - length: uint): uint {.discardable.} = - ## Perform ``CFB[T]`` decryption of encrypted data pointed by ``inp`` of - ## length ``length`` and store plain data to ``oup``. ``oup`` must be able to - ## hold at least ``length`` octets (bytes) of data. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. ``length`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``length mod ctx.sizeBlock == 0``. - ## - ## Procedure returns number of processed octets (bytes). - mixin encrypt - assert(not isNil(inp) and not isNil(oup)) - assert(length != 0) - var n = 0 - var i = 0'u - var ip = cast[ptr UncheckedArray[byte]](inp) - var op = cast[ptr UncheckedArray[byte]](oup) - var cp = cast[ptr UncheckedArray[byte]](addr ctx.iv[0]) - let mask = ctx.sizeBlock - - while i < length: - if n == 0: - ctx.cipher.encrypt(cast[ptr byte](cp), cast[ptr byte](cp)) - let c = ip[i] - op[i] = cp[n] xor c - cp[n] = c - inc(i) - n = (n + 1) mod mask - result = uint(n) - -proc encrypt*[T](ctx: var CFB[T], input: openarray[byte], - output: var openarray[byte]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc encrypt*[T](ctx: var CFB[T], input: openarray[char], - output: var openarray[char]) {.inline.} = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``CFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - encrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -proc decrypt*[T](ctx: var CFB[T], input: openarray[byte], - output: var openarray[byte]) = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, unsafeAddr input[0], addr output[0], uint(len(input))) - -proc decrypt*[T](ctx: var CFB[T], input: openarray[char], - output: var openarray[char]) = - ## Decrypt array of data ``input`` and store decrypted data to array - ## ``output`` using ``CFB[T]`` context ``ctx``. - ## - ## Note that length of ``input`` array must be less or equal to length of - ## ``output`` array. Length of ``input`` array must not be zero. - ## - ## Note, that this procedure do not perform any additional padding, so you - ## need to do it on your own. Length of ``input`` must be aligned to the - ## ``ctx.sizeBlock`` value, e.g. ``len(input) mod ctx.sizeBlock == 0``. - assert(len(input) <= len(output)) - assert(len(input) > 0) - decrypt(ctx, cast[ptr byte](unsafeAddr input[0]), - cast[ptr byte](addr output[0]), uint(len(input))) - -## GCM (Galois Counter Mode) - -# GHASH implementation is Nim version of `ghash_ctmul64.c` which is part -# of decent BearSSL project . -# Copyright (c) 2016 Thomas Pornin - -proc bmul64(x, y: uint64): uint64 = - var x0, x1, x2, x3, y0, y1, y2, y3, z0, z1, z2, z3: uint64 - x0 = x and 0x1111111111111111'u64 - x1 = x and 0x2222222222222222'u64 - x2 = x and 0x4444444444444444'u64 - x3 = x and 0x8888888888888888'u64 - y0 = y and 0x1111111111111111'u64 - y1 = y and 0x2222222222222222'u64 - y2 = y and 0x4444444444444444'u64 - y3 = y and 0x8888888888888888'u64 - z0 = (x0 * y0) xor (x1 * y3) xor (x2 * y2) xor (x3 * y1) - z1 = (x0 * y1) xor (x1 * y0) xor (x2 * y3) xor (x3 * y2) - z2 = (x0 * y2) xor (x1 * y1) xor (x2 * y0) xor (x3 * y3) - z3 = (x0 * y3) xor (x1 * y2) xor (x2 * y1) xor (x3 * y0) - z0 = z0 and 0x1111111111111111'u64 - z1 = z1 and 0x2222222222222222'u64 - z2 = z2 and 0x4444444444444444'u64 - z3 = z3 and 0x8888888888888888'u64 - result = z0 or z1 or z2 or z3 - -template RMS(x, m, s) = - x = ((x and uint64(m)) shl (s)) or ((x shr (s)) and uint64(m)) - -proc rev64(x: uint64): uint64 = - var xx = x - RMS(xx, 0x5555555555555555'u64, 1) - RMS(xx, 0x3333333333333333'u64, 2) - RMS(xx, 0x0F0F0F0F0F0F0F0F'u64, 4) - RMS(xx, 0x00FF00FF00FF00FF'u64, 8) - RMS(xx, 0x0000FFFF0000FFFF'u64, 16) - result = (xx shl 32) or (xx shr 32) - -proc ghash(y: var openarray[byte], h: openarray[byte], - data: ptr byte, size: int) = - var - y0, y1, h0, h1, h2, h0r, h1r, h2r: uint64 - buf: ptr byte - - y1 = EGETU64(addr y[0], 0) - y0 = EGETU64(addr y[0], 8) - h1 = EGETU64(unsafeAddr h[0], 0) - h0 = EGETU64(unsafeAddr h[0], 8) - h0r = rev64(h0) - h1r = rev64(h1) - h2 = h0 xor h1 - h2r = h0r xor h1r - - var length = size - buf = data - while length > 0: - var tmp: array[16, byte] - var src: ptr byte - var y0r, y1r, y2, y2r: uint64 - var z0, z1, z2, z0h, z1h, z2h, v0, v1, v2, v3: uint64 - - if length >= 16: - src = buf - buf = cast[ptr byte](cast[uint](buf) + 16) - length -= 16 - else: - zeroMem(addr tmp[0], 16) - copyMem(addr tmp[0], buf, length) - src = addr tmp[0] - length = 0 - - y1 = y1 xor GETU64(src, 0) - y0 = y0 xor GETU64(src, 8) - - y0r = rev64(y0) - y1r = rev64(y1) - y2 = y0 xor y1; - y2r = y0r xor y1r; - - z0 = bmul64(y0, h0) - z1 = bmul64(y1, h1) - z2 = bmul64(y2, h2) - z0h = bmul64(y0r, h0r) - z1h = bmul64(y1r, h1r) - z2h = bmul64(y2r, h2r) - z2 = z2 xor (z0 xor z1) - z2h = z2h xor (z0h xor z1h) - z0h = rev64(z0h) shr 1 - z1h = rev64(z1h) shr 1 - z2h = rev64(z2h) shr 1 - - v0 = z0 - v1 = z0h xor z2 - v2 = z1 xor z2h - v3 = z1h - - v3 = (v3 shl 1) or (v2 shr 63) - v2 = (v2 shl 1) or (v1 shr 63) - v1 = (v1 shl 1) or (v0 shr 63) - v0 = (v0 shl 1) - - v2 = v2 xor (v0 xor (v0 shr 1) xor (v0 shr 2) xor (v0 shr 7)) - v1 = v1 xor ((v0 shl 63) xor (v0 shl 62) xor (v0 shl 57)) - v3 = v3 xor (v1 xor (v1 shr 1) xor (v1 shr 2) xor (v1 shr 7)) - v2 = v2 xor ((v1 shl 63) xor (v1 shl 62) xor (v1 shl 57)) - - y0 = v2 - y1 = v3 - - EPUTU64(addr y, 0, y1) - EPUTU64(addr y, 8, y0) - -template sizeBlock*[T](ctx: GCM[T]): int = - ## Size of ``GCM[T]`` block in octets (bytes). This value is equal - ## to cipher ``T`` block size. - mixin sizeBlock - sizeBlock(ctx.cipher) - -template sizeKey*[T](ctx: GCM[T]): int = - ## Size of ``GCM[T]`` key in octets (bytes). This value is equal - ## to cipher ``T`` key size. - mixin sizeKey - sizeKey(ctx.cipher) - -proc init*[T](ctx: var GCM[T], key: openarray[byte], iv: openarray[byte], - aad: openarray[byte]) = - ## Initialize ``GCM[T]`` with encryption key ``key``, initial vector (IV) - ## ``iv`` and additional authentication data (AAD) ``aad``. - ## - ## Size of ``key`` must be at least ``ctx.sizeKey()`` octets (bytes). - ## Size of cipher ``T`` block must be 128 bits (16 bytes). - ## - ## You can see examples of usage GCM mode here ``examples/gcm.nim``. - mixin init - # GCM supports only 128bit block ciphers - assert(ctx.sizeBlock == 16) - assert(len(key) == ctx.sizeKey) - burnMem(ctx) - ctx.cipher.init(key) - ctx.cipher.encrypt(ctx.h, ctx.h) - if len(iv) == 12: - copyMem(addr ctx.y[0], unsafeAddr iv[0], 12) - inc128(ctx.y) - else: - var tmp: array[16, byte] - ghash(ctx.y, ctx.h, unsafeAddr iv[0], len(iv)) - EPUTU32(addr tmp[0], 12, len(iv) shl 3) - ghash(ctx.y, ctx.h, addr tmp[0], 16) - ctx.cipher.encrypt(ctx.y, ctx.basectr) - let slen = len(aad) - ctx.aadlen = uint64(slen) - ctx.datalen = 0 - if len(aad) > 0: - ghash(ctx.buf, ctx.h, unsafeAddr aad[0], slen) - -proc encrypt*[T](ctx: var GCM[T], input: openarray[byte], - output: var openarray[byte]) = - ## Encrypt array of data ``input`` and store encrypted data to array - ## ``output`` using ``GCM[T]`` context ``ctx``. - ## - ## Note that length of ``input`` must be less or equal to length of - ## ``output``. Length of ``input`` must not be zero. - mixin encrypt - var ectr: array[16, byte] - assert(len(input) <= len(output)) - assert(len(input) > 0) - var length = len(input) - var offset = 0 - ctx.datalen += uint64(length) - while length > 0: - let uselen = if length < 16: length else: 16 - inc128(ctx.y) - ctx.cipher.encrypt(ctx.y, ectr) - for i in 0.. 0) - - var length = len(input) - var offset = 0 - ctx.datalen += uint64(length) - while length > 0: - let uselen = if length < 16: length else: 16 - inc128(ctx.y) - ctx.cipher.encrypt(ctx.y, ectr) - for i in 0.. 0: - copyMem(addr tag[0], addr ctx.basectr[0], uselen) - EPUTU64(addr workbuf[0], 0, ctx.aadlen shl 3) - EPUTU64(addr workbuf[0], 8, ctx.datalen shl 3) - ghash(ctx.buf, ctx.h, addr workbuf[0], 16) - for i in 0..= ctx.sizeDigest: - for i in 0..= ctx.sizeDigest: - for i in 0..= ctx.sizeDigest) - discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data))) - -proc init*(ctx: var Blake2Context, key: ptr byte = nil, keylen: uint = 0'u) = - when ctx is Blake2sContext: - zeroMem(addr ctx.b[0], sizeof(byte) * 64) - ctx.h[0] = B2SIV[0]; ctx.h[1] = B2SIV[1] - ctx.h[2] = B2SIV[2]; ctx.h[3] = B2SIV[3] - ctx.h[4] = B2SIV[4]; ctx.h[5] = B2SIV[5] - ctx.h[6] = B2SIV[6]; ctx.h[7] = B2SIV[7] - let value = 0x01010000'u32 xor (cast[uint32](keylen) shl 8) xor - cast[uint32](ctx.sizeDigest) - else: - zeroMem(addr ctx.b[0], sizeof(byte) * 128) - ctx.h[0] = B2BIV[0]; ctx.h[1] = B2BIV[1] - ctx.h[2] = B2BIV[2]; ctx.h[3] = B2BIV[3] - ctx.h[4] = B2BIV[4]; ctx.h[5] = B2BIV[5] - ctx.h[6] = B2BIV[6]; ctx.h[7] = B2BIV[7] - let value = 0x01010000'u64 xor - (cast[uint64](keylen) shl 8) xor ctx.sizeDigest - - ctx.h[0] = ctx.h[0] xor value - ctx.t[0] = 0 - ctx.t[1] = 0 - ctx.c = 0 - - if not isNil(key) and keylen > 0'u: - ctx.update(key, keylen) - ctx.c = int(ctx.sizeBlock) - -proc init*[T: bchar](ctx: var Blake2Context, key: openarray[T]) {.inline.} = - if len(key) == 0: - ctx.init() - else: - ctx.init(cast[ptr byte](unsafeAddr key[0]), cast[uint](len(key))) - -proc clear*(ctx: var Blake2Context) {.inline.} = - burnMem(ctx) - -type - Blake2bParams* = object - b: array[64, byte] - Blake2sParams* = object - b: array[32, byte] - - Blake2Params* = Blake2bParams | Blake2sParams - -proc `digestLen=`*(p: var Blake2bParams; x: range[1..64]) = - p.b[0] = (uint8)x -proc `digestLen=`*(p: var Blake2sParams; x: range[1..32]) = - p.b[0] = (uint8)x -proc `keyLen=`*(p: var Blake2bParams; x: range[0..64]) = - p.b[1] = (uint8)x -proc `keyLen=`*(p: var Blake2sParams; x: range[0..32]) = - p.b[1] = (uint8)x -proc `fanout=`*(p: var Blake2Params; x: Natural) = - p.b[2] = (uint8)x -proc `depth=`*(p: var Blake2Params; x: Natural) = - p.b[3] = (uint8)x - -proc `leafLength=`*(p: var Blake2Params; x: Natural) = - var x = x; littleEndian32(p.b[4].addr, x.addr) - -proc `nodeOffset=`*(p: var Blake2bParams; x: Natural) = - var x = x; littleEndian64(p.b[8].addr, x.addr) -proc `nodeOffset=`*(p: var Blake2sParams; x: Natural) = - var tmp: int64 - littleEndian64(tmp.addr, p.b[8].addr) - tmp = (tmp and 0xffffffff) or (x shl 32) - littleEndian64(p.b[8].addr, tmp.addr) - -proc `nodeDepth=`*(p: var Blake2bParams; x: Natural) = - p.b[16] = (uint8)x -proc `nodeDepth=`*(p: var Blake2sParams; x: Natural) = - p.b[14] = (uint8)x - -proc `innerLength=`*(p: var Blake2bParams; x: Natural) = - p.b[17] = (uint8)x -proc `innerLength=`*(p: var Blake2sParams; x: Natural) = - p.b[15] = (uint8)x - -proc `salt=`*(p: var Blake2bParams; salt: pointer; len: Natural) = - copyMem(p.b[32].addr, salt, min(len, 16)) -proc `salt=`*(p: var Blake2sParams; salt: pointer; len: Natural) = - copyMem(p.b[16].addr, salt, min(len, 8)) - -proc `personal=`*(p: var Blake2bParams; salt: pointer; len: Natural) = - copyMem(p.b[48].addr, salt, min(len, 16)) -proc `personal=`*(p: var Blake2sParams; salt: pointer; len: Natural) = - copyMem(p.b[24].addr, salt, min(len, 8)) - -proc init*(ctx: var Blake2Context; - customize: proc(params: var Blake2Params); - key: pointer = nil, keylen = Natural(0)) = - ## Initialize a BLAKE2 context with a custom parameter block. - ## The `keyLen` and `digestLen` parameters are overriden after - ## customization, setting them in the callback has no effect. - ## - ## .. code-block:: nim - ## - ## var ctx: blake2_512 - ## ctx.init do (params: var Blake2bParams): - ## params.fanout = 4 - ## params.depth = 3 - ## params.salt = mySalt - ## - reset(ctx.b) - reset(ctx.t) - reset(ctx.c) - when ctx is Blake2bContext: - var params: Blake2bParams - else: - var params: Blake2sParams - params.fanout = 1 - params.depth = 1 - # default parameters - customize(params) - # custom parameters - params.keyLen = keylen - params.digestLen = ctx.sizeDigest - # implicit parameters - for i in 0..7: - when ctx is Blake2bContext: - ctx.h[i] = cast[array[8, uint64]](params.b)[i] xor B2BIV[i] - else: - ctx.h[i] = cast[array[8, uint32]](params.b)[i] xor B2SIV[i] - if not isNil(key) and keylen > 0: - ctx.update(key, keylen) - ctx.c = int(ctx.sizeBlock) diff --git a/src/blobsets/priv/nimcrypto/blowfish.nim b/src/blobsets/priv/nimcrypto/blowfish.nim deleted file mode 100644 index 2a80e9f..0000000 --- a/src/blobsets/priv/nimcrypto/blowfish.nim +++ /dev/null @@ -1,481 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements Blowfish crypto algorithm by Bruce Schneier -## -## Code based on `C implementation of the Blowfish algorithm` created by -## Paul Kocher [https://www.schneier.com/code/bfsh-koc.zip]. -## -## Tests made according to official test vectors by Eric Young -## [https://www.schneier.com/code/vectors.txt] and adopted version by -## Randy L. Milbert [https://www.schneier.com/code/vectors2.txt], except -## chaining mode tests. -## -## Implementation was made with "blowfish bug" in mind -## [https://www.schneier.com/blowfish-bug.txt] -## -## Some warnings from Paul Kocher: -## -## Warning #1: The code does not check key lengths. (Caveat encryptor.) -## Warning #2: Beware that Blowfish keys repeat such that "ab" = "abab". -## Warning #3: It is normally a good idea to zeroize the BLOWFISH_CTX before -## freeing it. -## Warning #4: Endianness conversions are the responsibility of the caller. -## (To encrypt bytes on a little-endian platforms, you'll probably want -## to swap bytes around instead of just casting.) -## Warning #5: Make sure to use a reasonable mode of operation for your -## application. (If you don't know what CBC mode is, see Warning #7.) -## Warning #6: This code is susceptible to timing attacks. -## Warning #7: Security engineering is risky and non-intuitive. Have someone -## check your work. If you don't know what you are doing, get help. - -import utils - -{.deadCodeElim:on.} - -const - N = 16 - - ORIG_P = [ 0x243F6A88'u32, 0x85A308D3'u32, 0x13198A2E'u32, 0x03707344'u32, - 0xA4093822'u32, 0x299F31D0'u32, 0x082EFA98'u32, 0xEC4E6C89'u32, - 0x452821E6'u32, 0x38D01377'u32, 0xBE5466CF'u32, 0x34E90C6C'u32, - 0xC0AC29B7'u32, 0xC97C50DD'u32, 0x3F84D5B5'u32, 0xB5470917'u32, - 0x9216D5D9'u32, 0x8979FB1B'u32 ] - ORIG_S = [ - [ - 0xD1310BA6'u32, 0x98DFB5AC'u32, 0x2FFD72DB'u32, 0xD01ADFB7'u32, - 0xB8E1AFED'u32, 0x6A267E96'u32, 0xBA7C9045'u32, 0xF12C7F99'u32, - 0x24A19947'u32, 0xB3916CF7'u32, 0x0801F2E2'u32, 0x858EFC16'u32, - 0x636920D8'u32, 0x71574E69'u32, 0xA458FEA3'u32, 0xF4933D7E'u32, - 0x0D95748F'u32, 0x728EB658'u32, 0x718BCD58'u32, 0x82154AEE'u32, - 0x7B54A41D'u32, 0xC25A59B5'u32, 0x9C30D539'u32, 0x2AF26013'u32, - 0xC5D1B023'u32, 0x286085F0'u32, 0xCA417918'u32, 0xB8DB38EF'u32, - 0x8E79DCB0'u32, 0x603A180E'u32, 0x6C9E0E8B'u32, 0xB01E8A3E'u32, - 0xD71577C1'u32, 0xBD314B27'u32, 0x78AF2FDA'u32, 0x55605C60'u32, - 0xE65525F3'u32, 0xAA55AB94'u32, 0x57489862'u32, 0x63E81440'u32, - 0x55CA396A'u32, 0x2AAB10B6'u32, 0xB4CC5C34'u32, 0x1141E8CE'u32, - 0xA15486AF'u32, 0x7C72E993'u32, 0xB3EE1411'u32, 0x636FBC2A'u32, - 0x2BA9C55D'u32, 0x741831F6'u32, 0xCE5C3E16'u32, 0x9B87931E'u32, - 0xAFD6BA33'u32, 0x6C24CF5C'u32, 0x7A325381'u32, 0x28958677'u32, - 0x3B8F4898'u32, 0x6B4BB9AF'u32, 0xC4BFE81B'u32, 0x66282193'u32, - 0x61D809CC'u32, 0xFB21A991'u32, 0x487CAC60'u32, 0x5DEC8032'u32, - 0xEF845D5D'u32, 0xE98575B1'u32, 0xDC262302'u32, 0xEB651B88'u32, - 0x23893E81'u32, 0xD396ACC5'u32, 0x0F6D6FF3'u32, 0x83F44239'u32, - 0x2E0B4482'u32, 0xA4842004'u32, 0x69C8F04A'u32, 0x9E1F9B5E'u32, - 0x21C66842'u32, 0xF6E96C9A'u32, 0x670C9C61'u32, 0xABD388F0'u32, - 0x6A51A0D2'u32, 0xD8542F68'u32, 0x960FA728'u32, 0xAB5133A3'u32, - 0x6EEF0B6C'u32, 0x137A3BE4'u32, 0xBA3BF050'u32, 0x7EFB2A98'u32, - 0xA1F1651D'u32, 0x39AF0176'u32, 0x66CA593E'u32, 0x82430E88'u32, - 0x8CEE8619'u32, 0x456F9FB4'u32, 0x7D84A5C3'u32, 0x3B8B5EBE'u32, - 0xE06F75D8'u32, 0x85C12073'u32, 0x401A449F'u32, 0x56C16AA6'u32, - 0x4ED3AA62'u32, 0x363F7706'u32, 0x1BFEDF72'u32, 0x429B023D'u32, - 0x37D0D724'u32, 0xD00A1248'u32, 0xDB0FEAD3'u32, 0x49F1C09B'u32, - 0x075372C9'u32, 0x80991B7B'u32, 0x25D479D8'u32, 0xF6E8DEF7'u32, - 0xE3FE501A'u32, 0xB6794C3B'u32, 0x976CE0BD'u32, 0x04C006BA'u32, - 0xC1A94FB6'u32, 0x409F60C4'u32, 0x5E5C9EC2'u32, 0x196A2463'u32, - 0x68FB6FAF'u32, 0x3E6C53B5'u32, 0x1339B2EB'u32, 0x3B52EC6F'u32, - 0x6DFC511F'u32, 0x9B30952C'u32, 0xCC814544'u32, 0xAF5EBD09'u32, - 0xBEE3D004'u32, 0xDE334AFD'u32, 0x660F2807'u32, 0x192E4BB3'u32, - 0xC0CBA857'u32, 0x45C8740F'u32, 0xD20B5F39'u32, 0xB9D3FBDB'u32, - 0x5579C0BD'u32, 0x1A60320A'u32, 0xD6A100C6'u32, 0x402C7279'u32, - 0x679F25FE'u32, 0xFB1FA3CC'u32, 0x8EA5E9F8'u32, 0xDB3222F8'u32, - 0x3C7516DF'u32, 0xFD616B15'u32, 0x2F501EC8'u32, 0xAD0552AB'u32, - 0x323DB5FA'u32, 0xFD238760'u32, 0x53317B48'u32, 0x3E00DF82'u32, - 0x9E5C57BB'u32, 0xCA6F8CA0'u32, 0x1A87562E'u32, 0xDF1769DB'u32, - 0xD542A8F6'u32, 0x287EFFC3'u32, 0xAC6732C6'u32, 0x8C4F5573'u32, - 0x695B27B0'u32, 0xBBCA58C8'u32, 0xE1FFA35D'u32, 0xB8F011A0'u32, - 0x10FA3D98'u32, 0xFD2183B8'u32, 0x4AFCB56C'u32, 0x2DD1D35B'u32, - 0x9A53E479'u32, 0xB6F84565'u32, 0xD28E49BC'u32, 0x4BFB9790'u32, - 0xE1DDF2DA'u32, 0xA4CB7E33'u32, 0x62FB1341'u32, 0xCEE4C6E8'u32, - 0xEF20CADA'u32, 0x36774C01'u32, 0xD07E9EFE'u32, 0x2BF11FB4'u32, - 0x95DBDA4D'u32, 0xAE909198'u32, 0xEAAD8E71'u32, 0x6B93D5A0'u32, - 0xD08ED1D0'u32, 0xAFC725E0'u32, 0x8E3C5B2F'u32, 0x8E7594B7'u32, - 0x8FF6E2FB'u32, 0xF2122B64'u32, 0x8888B812'u32, 0x900DF01C'u32, - 0x4FAD5EA0'u32, 0x688FC31C'u32, 0xD1CFF191'u32, 0xB3A8C1AD'u32, - 0x2F2F2218'u32, 0xBE0E1777'u32, 0xEA752DFE'u32, 0x8B021FA1'u32, - 0xE5A0CC0F'u32, 0xB56F74E8'u32, 0x18ACF3D6'u32, 0xCE89E299'u32, - 0xB4A84FE0'u32, 0xFD13E0B7'u32, 0x7CC43B81'u32, 0xD2ADA8D9'u32, - 0x165FA266'u32, 0x80957705'u32, 0x93CC7314'u32, 0x211A1477'u32, - 0xE6AD2065'u32, 0x77B5FA86'u32, 0xC75442F5'u32, 0xFB9D35CF'u32, - 0xEBCDAF0C'u32, 0x7B3E89A0'u32, 0xD6411BD3'u32, 0xAE1E7E49'u32, - 0x00250E2D'u32, 0x2071B35E'u32, 0x226800BB'u32, 0x57B8E0AF'u32, - 0x2464369B'u32, 0xF009B91E'u32, 0x5563911D'u32, 0x59DFA6AA'u32, - 0x78C14389'u32, 0xD95A537F'u32, 0x207D5BA2'u32, 0x02E5B9C5'u32, - 0x83260376'u32, 0x6295CFA9'u32, 0x11C81968'u32, 0x4E734A41'u32, - 0xB3472DCA'u32, 0x7B14A94A'u32, 0x1B510052'u32, 0x9A532915'u32, - 0xD60F573F'u32, 0xBC9BC6E4'u32, 0x2B60A476'u32, 0x81E67400'u32, - 0x08BA6FB5'u32, 0x571BE91F'u32, 0xF296EC6B'u32, 0x2A0DD915'u32, - 0xB6636521'u32, 0xE7B9F9B6'u32, 0xFF34052E'u32, 0xC5855664'u32, - 0x53B02D5D'u32, 0xA99F8FA1'u32, 0x08BA4799'u32, 0x6E85076A'u32 - ], - [ - 0x4B7A70E9'u32, 0xB5B32944'u32, 0xDB75092E'u32, 0xC4192623'u32, - 0xAD6EA6B0'u32, 0x49A7DF7D'u32, 0x9CEE60B8'u32, 0x8FEDB266'u32, - 0xECAA8C71'u32, 0x699A17FF'u32, 0x5664526C'u32, 0xC2B19EE1'u32, - 0x193602A5'u32, 0x75094C29'u32, 0xA0591340'u32, 0xE4183A3E'u32, - 0x3F54989A'u32, 0x5B429D65'u32, 0x6B8FE4D6'u32, 0x99F73FD6'u32, - 0xA1D29C07'u32, 0xEFE830F5'u32, 0x4D2D38E6'u32, 0xF0255DC1'u32, - 0x4CDD2086'u32, 0x8470EB26'u32, 0x6382E9C6'u32, 0x021ECC5E'u32, - 0x09686B3F'u32, 0x3EBAEFC9'u32, 0x3C971814'u32, 0x6B6A70A1'u32, - 0x687F3584'u32, 0x52A0E286'u32, 0xB79C5305'u32, 0xAA500737'u32, - 0x3E07841C'u32, 0x7FDEAE5C'u32, 0x8E7D44EC'u32, 0x5716F2B8'u32, - 0xB03ADA37'u32, 0xF0500C0D'u32, 0xF01C1F04'u32, 0x0200B3FF'u32, - 0xAE0CF51A'u32, 0x3CB574B2'u32, 0x25837A58'u32, 0xDC0921BD'u32, - 0xD19113F9'u32, 0x7CA92FF6'u32, 0x94324773'u32, 0x22F54701'u32, - 0x3AE5E581'u32, 0x37C2DADC'u32, 0xC8B57634'u32, 0x9AF3DDA7'u32, - 0xA9446146'u32, 0x0FD0030E'u32, 0xECC8C73E'u32, 0xA4751E41'u32, - 0xE238CD99'u32, 0x3BEA0E2F'u32, 0x3280BBA1'u32, 0x183EB331'u32, - 0x4E548B38'u32, 0x4F6DB908'u32, 0x6F420D03'u32, 0xF60A04BF'u32, - 0x2CB81290'u32, 0x24977C79'u32, 0x5679B072'u32, 0xBCAF89AF'u32, - 0xDE9A771F'u32, 0xD9930810'u32, 0xB38BAE12'u32, 0xDCCF3F2E'u32, - 0x5512721F'u32, 0x2E6B7124'u32, 0x501ADDE6'u32, 0x9F84CD87'u32, - 0x7A584718'u32, 0x7408DA17'u32, 0xBC9F9ABC'u32, 0xE94B7D8C'u32, - 0xEC7AEC3A'u32, 0xDB851DFA'u32, 0x63094366'u32, 0xC464C3D2'u32, - 0xEF1C1847'u32, 0x3215D908'u32, 0xDD433B37'u32, 0x24C2BA16'u32, - 0x12A14D43'u32, 0x2A65C451'u32, 0x50940002'u32, 0x133AE4DD'u32, - 0x71DFF89E'u32, 0x10314E55'u32, 0x81AC77D6'u32, 0x5F11199B'u32, - 0x043556F1'u32, 0xD7A3C76B'u32, 0x3C11183B'u32, 0x5924A509'u32, - 0xF28FE6ED'u32, 0x97F1FBFA'u32, 0x9EBABF2C'u32, 0x1E153C6E'u32, - 0x86E34570'u32, 0xEAE96FB1'u32, 0x860E5E0A'u32, 0x5A3E2AB3'u32, - 0x771FE71C'u32, 0x4E3D06FA'u32, 0x2965DCB9'u32, 0x99E71D0F'u32, - 0x803E89D6'u32, 0x5266C825'u32, 0x2E4CC978'u32, 0x9C10B36A'u32, - 0xC6150EBA'u32, 0x94E2EA78'u32, 0xA5FC3C53'u32, 0x1E0A2DF4'u32, - 0xF2F74EA7'u32, 0x361D2B3D'u32, 0x1939260F'u32, 0x19C27960'u32, - 0x5223A708'u32, 0xF71312B6'u32, 0xEBADFE6E'u32, 0xEAC31F66'u32, - 0xE3BC4595'u32, 0xA67BC883'u32, 0xB17F37D1'u32, 0x018CFF28'u32, - 0xC332DDEF'u32, 0xBE6C5AA5'u32, 0x65582185'u32, 0x68AB9802'u32, - 0xEECEA50F'u32, 0xDB2F953B'u32, 0x2AEF7DAD'u32, 0x5B6E2F84'u32, - 0x1521B628'u32, 0x29076170'u32, 0xECDD4775'u32, 0x619F1510'u32, - 0x13CCA830'u32, 0xEB61BD96'u32, 0x0334FE1E'u32, 0xAA0363CF'u32, - 0xB5735C90'u32, 0x4C70A239'u32, 0xD59E9E0B'u32, 0xCBAADE14'u32, - 0xEECC86BC'u32, 0x60622CA7'u32, 0x9CAB5CAB'u32, 0xB2F3846E'u32, - 0x648B1EAF'u32, 0x19BDF0CA'u32, 0xA02369B9'u32, 0x655ABB50'u32, - 0x40685A32'u32, 0x3C2AB4B3'u32, 0x319EE9D5'u32, 0xC021B8F7'u32, - 0x9B540B19'u32, 0x875FA099'u32, 0x95F7997E'u32, 0x623D7DA8'u32, - 0xF837889A'u32, 0x97E32D77'u32, 0x11ED935F'u32, 0x16681281'u32, - 0x0E358829'u32, 0xC7E61FD6'u32, 0x96DEDFA1'u32, 0x7858BA99'u32, - 0x57F584A5'u32, 0x1B227263'u32, 0x9B83C3FF'u32, 0x1AC24696'u32, - 0xCDB30AEB'u32, 0x532E3054'u32, 0x8FD948E4'u32, 0x6DBC3128'u32, - 0x58EBF2EF'u32, 0x34C6FFEA'u32, 0xFE28ED61'u32, 0xEE7C3C73'u32, - 0x5D4A14D9'u32, 0xE864B7E3'u32, 0x42105D14'u32, 0x203E13E0'u32, - 0x45EEE2B6'u32, 0xA3AAABEA'u32, 0xDB6C4F15'u32, 0xFACB4FD0'u32, - 0xC742F442'u32, 0xEF6ABBB5'u32, 0x654F3B1D'u32, 0x41CD2105'u32, - 0xD81E799E'u32, 0x86854DC7'u32, 0xE44B476A'u32, 0x3D816250'u32, - 0xCF62A1F2'u32, 0x5B8D2646'u32, 0xFC8883A0'u32, 0xC1C7B6A3'u32, - 0x7F1524C3'u32, 0x69CB7492'u32, 0x47848A0B'u32, 0x5692B285'u32, - 0x095BBF00'u32, 0xAD19489D'u32, 0x1462B174'u32, 0x23820E00'u32, - 0x58428D2A'u32, 0x0C55F5EA'u32, 0x1DADF43E'u32, 0x233F7061'u32, - 0x3372F092'u32, 0x8D937E41'u32, 0xD65FECF1'u32, 0x6C223BDB'u32, - 0x7CDE3759'u32, 0xCBEE7460'u32, 0x4085F2A7'u32, 0xCE77326E'u32, - 0xA6078084'u32, 0x19F8509E'u32, 0xE8EFD855'u32, 0x61D99735'u32, - 0xA969A7AA'u32, 0xC50C06C2'u32, 0x5A04ABFC'u32, 0x800BCADC'u32, - 0x9E447A2E'u32, 0xC3453484'u32, 0xFDD56705'u32, 0x0E1E9EC9'u32, - 0xDB73DBD3'u32, 0x105588CD'u32, 0x675FDA79'u32, 0xE3674340'u32, - 0xC5C43465'u32, 0x713E38D8'u32, 0x3D28F89E'u32, 0xF16DFF20'u32, - 0x153E21E7'u32, 0x8FB03D4A'u32, 0xE6E39F2B'u32, 0xDB83ADF7'u32 - ], - [ - 0xE93D5A68'u32, 0x948140F7'u32, 0xF64C261C'u32, 0x94692934'u32, - 0x411520F7'u32, 0x7602D4F7'u32, 0xBCF46B2E'u32, 0xD4A20068'u32, - 0xD4082471'u32, 0x3320F46A'u32, 0x43B7D4B7'u32, 0x500061AF'u32, - 0x1E39F62E'u32, 0x97244546'u32, 0x14214F74'u32, 0xBF8B8840'u32, - 0x4D95FC1D'u32, 0x96B591AF'u32, 0x70F4DDD3'u32, 0x66A02F45'u32, - 0xBFBC09EC'u32, 0x03BD9785'u32, 0x7FAC6DD0'u32, 0x31CB8504'u32, - 0x96EB27B3'u32, 0x55FD3941'u32, 0xDA2547E6'u32, 0xABCA0A9A'u32, - 0x28507825'u32, 0x530429F4'u32, 0x0A2C86DA'u32, 0xE9B66DFB'u32, - 0x68DC1462'u32, 0xD7486900'u32, 0x680EC0A4'u32, 0x27A18DEE'u32, - 0x4F3FFEA2'u32, 0xE887AD8C'u32, 0xB58CE006'u32, 0x7AF4D6B6'u32, - 0xAACE1E7C'u32, 0xD3375FEC'u32, 0xCE78A399'u32, 0x406B2A42'u32, - 0x20FE9E35'u32, 0xD9F385B9'u32, 0xEE39D7AB'u32, 0x3B124E8B'u32, - 0x1DC9FAF7'u32, 0x4B6D1856'u32, 0x26A36631'u32, 0xEAE397B2'u32, - 0x3A6EFA74'u32, 0xDD5B4332'u32, 0x6841E7F7'u32, 0xCA7820FB'u32, - 0xFB0AF54E'u32, 0xD8FEB397'u32, 0x454056AC'u32, 0xBA489527'u32, - 0x55533A3A'u32, 0x20838D87'u32, 0xFE6BA9B7'u32, 0xD096954B'u32, - 0x55A867BC'u32, 0xA1159A58'u32, 0xCCA92963'u32, 0x99E1DB33'u32, - 0xA62A4A56'u32, 0x3F3125F9'u32, 0x5EF47E1C'u32, 0x9029317C'u32, - 0xFDF8E802'u32, 0x04272F70'u32, 0x80BB155C'u32, 0x05282CE3'u32, - 0x95C11548'u32, 0xE4C66D22'u32, 0x48C1133F'u32, 0xC70F86DC'u32, - 0x07F9C9EE'u32, 0x41041F0F'u32, 0x404779A4'u32, 0x5D886E17'u32, - 0x325F51EB'u32, 0xD59BC0D1'u32, 0xF2BCC18F'u32, 0x41113564'u32, - 0x257B7834'u32, 0x602A9C60'u32, 0xDFF8E8A3'u32, 0x1F636C1B'u32, - 0x0E12B4C2'u32, 0x02E1329E'u32, 0xAF664FD1'u32, 0xCAD18115'u32, - 0x6B2395E0'u32, 0x333E92E1'u32, 0x3B240B62'u32, 0xEEBEB922'u32, - 0x85B2A20E'u32, 0xE6BA0D99'u32, 0xDE720C8C'u32, 0x2DA2F728'u32, - 0xD0127845'u32, 0x95B794FD'u32, 0x647D0862'u32, 0xE7CCF5F0'u32, - 0x5449A36F'u32, 0x877D48FA'u32, 0xC39DFD27'u32, 0xF33E8D1E'u32, - 0x0A476341'u32, 0x992EFF74'u32, 0x3A6F6EAB'u32, 0xF4F8FD37'u32, - 0xA812DC60'u32, 0xA1EBDDF8'u32, 0x991BE14C'u32, 0xDB6E6B0D'u32, - 0xC67B5510'u32, 0x6D672C37'u32, 0x2765D43B'u32, 0xDCD0E804'u32, - 0xF1290DC7'u32, 0xCC00FFA3'u32, 0xB5390F92'u32, 0x690FED0B'u32, - 0x667B9FFB'u32, 0xCEDB7D9C'u32, 0xA091CF0B'u32, 0xD9155EA3'u32, - 0xBB132F88'u32, 0x515BAD24'u32, 0x7B9479BF'u32, 0x763BD6EB'u32, - 0x37392EB3'u32, 0xCC115979'u32, 0x8026E297'u32, 0xF42E312D'u32, - 0x6842ADA7'u32, 0xC66A2B3B'u32, 0x12754CCC'u32, 0x782EF11C'u32, - 0x6A124237'u32, 0xB79251E7'u32, 0x06A1BBE6'u32, 0x4BFB6350'u32, - 0x1A6B1018'u32, 0x11CAEDFA'u32, 0x3D25BDD8'u32, 0xE2E1C3C9'u32, - 0x44421659'u32, 0x0A121386'u32, 0xD90CEC6E'u32, 0xD5ABEA2A'u32, - 0x64AF674E'u32, 0xDA86A85F'u32, 0xBEBFE988'u32, 0x64E4C3FE'u32, - 0x9DBC8057'u32, 0xF0F7C086'u32, 0x60787BF8'u32, 0x6003604D'u32, - 0xD1FD8346'u32, 0xF6381FB0'u32, 0x7745AE04'u32, 0xD736FCCC'u32, - 0x83426B33'u32, 0xF01EAB71'u32, 0xB0804187'u32, 0x3C005E5F'u32, - 0x77A057BE'u32, 0xBDE8AE24'u32, 0x55464299'u32, 0xBF582E61'u32, - 0x4E58F48F'u32, 0xF2DDFDA2'u32, 0xF474EF38'u32, 0x8789BDC2'u32, - 0x5366F9C3'u32, 0xC8B38E74'u32, 0xB475F255'u32, 0x46FCD9B9'u32, - 0x7AEB2661'u32, 0x8B1DDF84'u32, 0x846A0E79'u32, 0x915F95E2'u32, - 0x466E598E'u32, 0x20B45770'u32, 0x8CD55591'u32, 0xC902DE4C'u32, - 0xB90BACE1'u32, 0xBB8205D0'u32, 0x11A86248'u32, 0x7574A99E'u32, - 0xB77F19B6'u32, 0xE0A9DC09'u32, 0x662D09A1'u32, 0xC4324633'u32, - 0xE85A1F02'u32, 0x09F0BE8C'u32, 0x4A99A025'u32, 0x1D6EFE10'u32, - 0x1AB93D1D'u32, 0x0BA5A4DF'u32, 0xA186F20F'u32, 0x2868F169'u32, - 0xDCB7DA83'u32, 0x573906FE'u32, 0xA1E2CE9B'u32, 0x4FCD7F52'u32, - 0x50115E01'u32, 0xA70683FA'u32, 0xA002B5C4'u32, 0x0DE6D027'u32, - 0x9AF88C27'u32, 0x773F8641'u32, 0xC3604C06'u32, 0x61A806B5'u32, - 0xF0177A28'u32, 0xC0F586E0'u32, 0x006058AA'u32, 0x30DC7D62'u32, - 0x11E69ED7'u32, 0x2338EA63'u32, 0x53C2DD94'u32, 0xC2C21634'u32, - 0xBBCBEE56'u32, 0x90BCB6DE'u32, 0xEBFC7DA1'u32, 0xCE591D76'u32, - 0x6F05E409'u32, 0x4B7C0188'u32, 0x39720A3D'u32, 0x7C927C24'u32, - 0x86E3725F'u32, 0x724D9DB9'u32, 0x1AC15BB4'u32, 0xD39EB8FC'u32, - 0xED545578'u32, 0x08FCA5B5'u32, 0xD83D7CD3'u32, 0x4DAD0FC4'u32, - 0x1E50EF5E'u32, 0xB161E6F8'u32, 0xA28514D9'u32, 0x6C51133C'u32, - 0x6FD5C7E7'u32, 0x56E14EC4'u32, 0x362ABFCE'u32, 0xDDC6C837'u32, - 0xD79A3234'u32, 0x92638212'u32, 0x670EFA8E'u32, 0x406000E0'u32 - ], - [ - 0x3A39CE37'u32, 0xD3FAF5CF'u32, 0xABC27737'u32, 0x5AC52D1B'u32, - 0x5CB0679E'u32, 0x4FA33742'u32, 0xD3822740'u32, 0x99BC9BBE'u32, - 0xD5118E9D'u32, 0xBF0F7315'u32, 0xD62D1C7E'u32, 0xC700C47B'u32, - 0xB78C1B6B'u32, 0x21A19045'u32, 0xB26EB1BE'u32, 0x6A366EB4'u32, - 0x5748AB2F'u32, 0xBC946E79'u32, 0xC6A376D2'u32, 0x6549C2C8'u32, - 0x530FF8EE'u32, 0x468DDE7D'u32, 0xD5730A1D'u32, 0x4CD04DC6'u32, - 0x2939BBDB'u32, 0xA9BA4650'u32, 0xAC9526E8'u32, 0xBE5EE304'u32, - 0xA1FAD5F0'u32, 0x6A2D519A'u32, 0x63EF8CE2'u32, 0x9A86EE22'u32, - 0xC089C2B8'u32, 0x43242EF6'u32, 0xA51E03AA'u32, 0x9CF2D0A4'u32, - 0x83C061BA'u32, 0x9BE96A4D'u32, 0x8FE51550'u32, 0xBA645BD6'u32, - 0x2826A2F9'u32, 0xA73A3AE1'u32, 0x4BA99586'u32, 0xEF5562E9'u32, - 0xC72FEFD3'u32, 0xF752F7DA'u32, 0x3F046F69'u32, 0x77FA0A59'u32, - 0x80E4A915'u32, 0x87B08601'u32, 0x9B09E6AD'u32, 0x3B3EE593'u32, - 0xE990FD5A'u32, 0x9E34D797'u32, 0x2CF0B7D9'u32, 0x022B8B51'u32, - 0x96D5AC3A'u32, 0x017DA67D'u32, 0xD1CF3ED6'u32, 0x7C7D2D28'u32, - 0x1F9F25CF'u32, 0xADF2B89B'u32, 0x5AD6B472'u32, 0x5A88F54C'u32, - 0xE029AC71'u32, 0xE019A5E6'u32, 0x47B0ACFD'u32, 0xED93FA9B'u32, - 0xE8D3C48D'u32, 0x283B57CC'u32, 0xF8D56629'u32, 0x79132E28'u32, - 0x785F0191'u32, 0xED756055'u32, 0xF7960E44'u32, 0xE3D35E8C'u32, - 0x15056DD4'u32, 0x88F46DBA'u32, 0x03A16125'u32, 0x0564F0BD'u32, - 0xC3EB9E15'u32, 0x3C9057A2'u32, 0x97271AEC'u32, 0xA93A072A'u32, - 0x1B3F6D9B'u32, 0x1E6321F5'u32, 0xF59C66FB'u32, 0x26DCF319'u32, - 0x7533D928'u32, 0xB155FDF5'u32, 0x03563482'u32, 0x8ABA3CBB'u32, - 0x28517711'u32, 0xC20AD9F8'u32, 0xABCC5167'u32, 0xCCAD925F'u32, - 0x4DE81751'u32, 0x3830DC8E'u32, 0x379D5862'u32, 0x9320F991'u32, - 0xEA7A90C2'u32, 0xFB3E7BCE'u32, 0x5121CE64'u32, 0x774FBE32'u32, - 0xA8B6E37E'u32, 0xC3293D46'u32, 0x48DE5369'u32, 0x6413E680'u32, - 0xA2AE0810'u32, 0xDD6DB224'u32, 0x69852DFD'u32, 0x09072166'u32, - 0xB39A460A'u32, 0x6445C0DD'u32, 0x586CDECF'u32, 0x1C20C8AE'u32, - 0x5BBEF7DD'u32, 0x1B588D40'u32, 0xCCD2017F'u32, 0x6BB4E3BB'u32, - 0xDDA26A7E'u32, 0x3A59FF45'u32, 0x3E350A44'u32, 0xBCB4CDD5'u32, - 0x72EACEA8'u32, 0xFA6484BB'u32, 0x8D6612AE'u32, 0xBF3C6F47'u32, - 0xD29BE463'u32, 0x542F5D9E'u32, 0xAEC2771B'u32, 0xF64E6370'u32, - 0x740E0D8D'u32, 0xE75B1357'u32, 0xF8721671'u32, 0xAF537D5D'u32, - 0x4040CB08'u32, 0x4EB4E2CC'u32, 0x34D2466A'u32, 0x0115AF84'u32, - 0xE1B00428'u32, 0x95983A1D'u32, 0x06B89FB4'u32, 0xCE6EA048'u32, - 0x6F3F3B82'u32, 0x3520AB82'u32, 0x011A1D4B'u32, 0x277227F8'u32, - 0x611560B1'u32, 0xE7933FDC'u32, 0xBB3A792B'u32, 0x344525BD'u32, - 0xA08839E1'u32, 0x51CE794B'u32, 0x2F32C9B7'u32, 0xA01FBAC9'u32, - 0xE01CC87E'u32, 0xBCC7D1F6'u32, 0xCF0111C3'u32, 0xA1E8AAC7'u32, - 0x1A908749'u32, 0xD44FBD9A'u32, 0xD0DADECB'u32, 0xD50ADA38'u32, - 0x0339C32A'u32, 0xC6913667'u32, 0x8DF9317C'u32, 0xE0B12B4F'u32, - 0xF79E59B7'u32, 0x43F5BB3A'u32, 0xF2D519FF'u32, 0x27D9459C'u32, - 0xBF97222C'u32, 0x15E6FC2A'u32, 0x0F91FC71'u32, 0x9B941525'u32, - 0xFAE59361'u32, 0xCEB69CEB'u32, 0xC2A86459'u32, 0x12BAA8D1'u32, - 0xB6C1075E'u32, 0xE3056A0C'u32, 0x10D25065'u32, 0xCB03A442'u32, - 0xE0EC6E0E'u32, 0x1698DB3B'u32, 0x4C98A0BE'u32, 0x3278E964'u32, - 0x9F1F9532'u32, 0xE0D392DF'u32, 0xD3A0342B'u32, 0x8971F21E'u32, - 0x1B0A7441'u32, 0x4BA3348C'u32, 0xC5BE7120'u32, 0xC37632D8'u32, - 0xDF359F8D'u32, 0x9B992F2E'u32, 0xE60B6F47'u32, 0x0FE3F11D'u32, - 0xE54CDA54'u32, 0x1EDAD891'u32, 0xCE6279CF'u32, 0xCD3E7E6F'u32, - 0x1618B166'u32, 0xFD2C1D05'u32, 0x848FD2C5'u32, 0xF6FB2299'u32, - 0xF523F357'u32, 0xA6327623'u32, 0x93A83531'u32, 0x56CCCD02'u32, - 0xACF08162'u32, 0x5A75EBB5'u32, 0x6E163697'u32, 0x88D273CC'u32, - 0xDE966292'u32, 0x81B949D0'u32, 0x4C50901B'u32, 0x71C65614'u32, - 0xE6C6C7BD'u32, 0x327A140A'u32, 0x45E1D006'u32, 0xC3F27B9A'u32, - 0xC9AA53FD'u32, 0x62A80F00'u32, 0xBB25BFE2'u32, 0x35BDD2F6'u32, - 0x71126905'u32, 0xB2040222'u32, 0xB6CBCF7C'u32, 0xCD769C2B'u32, - 0x53113EC0'u32, 0x1640E3D3'u32, 0x38ABBD60'u32, 0x2547ADF0'u32, - 0xBA38209C'u32, 0xF746CE76'u32, 0x77AFA1C5'u32, 0x20756060'u32, - 0x85CBFE4E'u32, 0x8AE88DD8'u32, 0x7AAAF9B0'u32, 0x4CF9AA7E'u32, - 0x1948C25C'u32, 0x02FB8A8C'u32, 0x01C36AE4'u32, 0xD6EBE1F9'u32, - 0x90D4F869'u32, 0xA65CDEA0'u32, 0x3F09252D'u32, 0xC208E69F'u32, - 0xB74E6132'u32, 0xCE77E25B'u32, 0x578FDFE3'u32, 0x3AC372E6'u32 - ] - ] - -type - BlowfishContext[bits: static[uint]] = object - sizeKey: int - P: array[16 + 2, uint32] - S: array[4, array[256, uint32]] - - blowfish* = BlowfishContext[64] - -template f(ctx: var BlowfishContext, x: uint32): uint32 = - var vx = x - var d = cast[uint16](vx and 0xFF'u32) - vx = vx shr 8 - var c = cast[uint16](vx and 0xFF'u32) - vx = vx shr 8 - var b = cast[uint16](vx and 0xFF'u32) - vx = vx shr 8 - var a = cast[uint16](vx and 0xFF'u32) - var vy = ctx.S[0][a] + ctx.S[1][b] - vy = vy xor ctx.S[2][c] - vy = vy + ctx.S[3][d] - vy - -proc blowfishEncrypt*(ctx: var BlowfishContext, inp: ptr byte, - oup: ptr byte) = - var nxl = BSWAP(GET_DWORD(inp, 0)) - var nxr = BSWAP(GET_DWORD(inp, 1)) - - var temp = 0'u32 - var i = 0'i16 - - while i < N: - nxl = nxl xor ctx.P[i] - nxr = f(ctx, nxl) xor nxr - temp = nxl - nxl = nxr - nxr = temp - inc(i) - - temp = nxl - nxl = nxr - nxr = temp - - nxr = nxr xor ctx.P[N] - nxl = nxl xor ctx.P[N + 1] - - SET_DWORD(oup, 0, BSWAP(nxl)) - SET_DWORD(oup, 1, BSWAP(nxr)) - -proc blowfishDecrypt*(ctx: var BlowfishContext, inp: ptr byte, - oup: ptr byte) = - var nxl = BSWAP(GET_DWORD(inp, 0)) - var nxr = BSWAP(GET_DWORD(inp, 1)) - var temp = 0'u32 - - var i = N + 1 - while i > 1: - nxl = nxl xor ctx.P[i] - nxr = f(ctx, nxl) xor nxr - temp = nxl - nxl = nxr - nxr = temp - dec(i) - - temp = nxl - nxl = nxr - nxr = temp - - nxr = nxr xor ctx.P[1] - nxl = nxl xor ctx.P[0] - - SET_DWORD(oup, 0, BSWAP(nxl)) - SET_DWORD(oup, 1, BSWAP(nxr)) - -proc initBlowfishContext*(ctx: var BlowfishContext, key: ptr byte, nkey: int) = - var i = 0 - var j = 0 - var k = 0 - var data = 0'u32 - var length = nkey div 8 - - while i < 4: - j = 0 - while j < 256: - ctx.S[i][j] = ORIG_S[i][j] - inc(j) - inc(i) - - j = 0 - i = 0 - while i < N + 2: - data = 0 - k = 0 - while k < 4: - data = data shl 8 - data = data or (GETU8(key, j) and 0xFF) - inc(j) - if j >= length: - j = 0 - inc(k) - ctx.P[i] = ORIG_P[i] xor data - inc(i) - - i = 0 - var datarl = [0'u32, 0'u32] - while i < N + 2: - blowfishEncrypt(ctx, cast[ptr byte](addr datarl[0]), - cast[ptr byte](addr datarl[0])) - ctx.P[i] = datarl[0] - ctx.P[i + 1] = datarl[1] - i = i + 2 - - i = 0 - while i < 4: - j = 0 - while j < 256: - blowfishEncrypt(ctx, cast[ptr byte](addr datarl[0]), - cast[ptr byte](addr datarl[0])) - ctx.S[i][j] = datarl[0] - ctx.S[i][j + 1] = datarl[1] - j = j + 2 - inc(i) - -template sizeKey*(ctx: BlowfishContext): int = - (ctx.sizeKey shr 3) - -template sizeBlock*(ctx: BlowfishContext): int = - (8) - -template sizeKey*(r: typedesc[blowfish]): int = - {.error: "Could not obtain key size of Blowfish cipher at compile-time".} - -template sizeBlock*(r: typedesc[blowfish]): int = - (8) - -proc init*(ctx: var BlowfishContext, key: ptr byte, nkey: int) {.inline.} = - ctx.sizeKey = nkey shl 3 - initBlowfishContext(ctx, key, ctx.sizeKey) - -proc init*(ctx: var BlowfishContext, key: openarray[byte]) {.inline.} = - assert(len(key) > 0) - ctx.sizeKey = len(key) shl 3 - initBlowfishContext(ctx, unsafeAddr key[0], ctx.sizeKey) - -proc clear*(ctx: var BlowfishContext) {.inline.} = - burnMem(ctx) - -proc encrypt*(ctx: var BlowfishContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - blowfishEncrypt(ctx, inbytes, outbytes) - -proc decrypt*(ctx: var BlowfishContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - blowfishDecrypt(ctx, inbytes, outbytes) - -proc encrypt*(ctx: var BlowfishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - blowfishEncrypt(ctx, unsafeAddr input[0], addr output[0]) - -proc decrypt*(ctx: var BlowfishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - blowfishDecrypt(ctx, unsafeAddr input[0], addr output[0]) diff --git a/src/blobsets/priv/nimcrypto/hash.nim b/src/blobsets/priv/nimcrypto/hash.nim deleted file mode 100644 index dc3be55..0000000 --- a/src/blobsets/priv/nimcrypto/hash.nim +++ /dev/null @@ -1,150 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module provides helper procedures for calculating secure digests -## supported by `nimcrypto` library. -import utils - -{.deadCodeElim:on.} - -const - MaxMDigestLength* = 64 - ## Maximum size of generated digests by `nimcrypto` library is 64 octets. - -type - MDigest*[bits: static[int]] = object - ## Message digest type - data*: array[bits div 8, byte] - - bchar* = byte | char - -proc `$`*(digest: MDigest): string = - ## Return hexadecimal string representation of ``digest``. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var digestHexString = $sha256.digest("Hello World!") - ## echo digestHexString - result = "" - var i = 0'u - while i < uint(len(digest.data)): - result &= hexChar(cast[byte](digest.data[i])) - inc(i) - -proc digest*(HashType: typedesc, data: ptr byte, - ulen: uint): MDigest[HashType.bits] = - ## Calculate and return digest using algorithm ``HashType`` of data ``data`` - ## with length ``ulen``. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var stringToHash = "Hello World!" - ## let data = cast[ptr byte](addr stringToHash[0]) - ## let datalen = uint(len(stringToHash)) - ## echo sha256.digest(data, datalen) - mixin init, update, finish, clear - var ctx: HashType - ctx.init() - ctx.update(data, ulen) - result = ctx.finish() - ctx.clear() - -proc digest*[T](HashType: typedesc, data: openarray[T], - ostart: int = 0, ofinish: int = -1): MDigest[HashType.bits] = - ## Calculate and return digest using algorithm ``HashType`` of data ``data`` - ## in slice ``[ostart, ofinish]``, both ``ostart`` and ``ofinish`` are - ## inclusive. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var stringToHash = "Hello World!" - ## ## Calculate digest of whole string `Hello World!`. - ## echo sha256.digest(stringToHash) - ## ## Calcualte digest of `Hello`. - ## echo sha256.digest(stringToHash, ofinish = 4) - ## ## Calculate digest of `World!`. - ## echo sha256.digest(stringToHash, ostart = 6) - ## ## Calculate digest of constant `Hello`. - ## echo sha256.digest("Hello") - ## ## Calculate digest of constant `World!`. - ## echo sha256.digest("World!") - mixin init, update, finish, clear - var ctx: HashType - let so = if ostart < 0: (len(data) + ostart) else: ostart - let eo = if ofinish < 0: (len(data) + ofinish) else: ofinish - let length = (eo - so + 1) * sizeof(T) - ctx.init() - if length <= 0: - result = ctx.finish() - else: - ctx.update(cast[ptr byte](unsafeAddr data[so]), uint(length)) - result = ctx.finish() - ctx.clear() - -proc fromHex*(T: typedesc[MDigest], s: string): T = - ## Create ``MDigest`` object from hexadecimal string representation. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var a = MDigest[256].fromHex("7F83B1657FF1FC53B92DC18148A1D65DFC2D4B1FA3D677284ADDD200126D9069") - ## echo $a - ## ## Get number of bits used by ``a``. - ## echo a.bits - hexToBytes(s, result.data) - -proc `==`*[A, B](d1: MDigest[A], d2: MDigest[B]): bool = - ## Check for equality between two ``MDigest`` objects ``d1`` and ``d2``. - ## If size in bits of ``d1`` is not equal to size in bits of ``d2`` then - ## digests considered as not equal. - if d1.bits != d2.bits: - return false - var n = len(d1.data) - var res, diff: int - while n > 0: - dec(n) - diff = int(d1.data[n]) - int(d2.data[n]) - res = (res and -not(diff)) or diff - result = (res == 0) - -when true: - proc toDigestAux(n: static int, s: static string): MDigest[n] = - static: - assert n > 0 and n mod 8 == 0, - "The provided hex string should have an even non-zero length" - hexToBytes(s, result.data) - - template toDigest*(s: static string): auto = - ## Convert hexadecimal string representation to ``MDigest`` object. - ## This template can be used to create ``MDigest`` constants. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## const SomeDigest = "7F83B1657FF1FC53B92DC18148A1D65DFC2D4B1FA3D677284ADDD200126D9069".toDigest - ## echo $SomeDigest - ## ## Get number of bits used by ``SomeDigest``. - ## echo SomeDigest.bits - const digest = toDigestAux(len(s) * 4, s) - digest - -else: - # This definition is shorter, but it turns out that it - # triggers a Nim bug. Calls to `toDigest` will compile, - # but the result values won't be considered the same - # type as MDigest[N] even when s.len * 4 == N - proc toDigest*(s: static string): MDigest[s.len * 4] = - static: - assert s.len > 0 and s.len mod 2 == 0, - "The provided hex string should have an even non-zero length" - const digest = hexToBytes(s, result.data) - return digest diff --git a/src/blobsets/priv/nimcrypto/hmac.nim b/src/blobsets/priv/nimcrypto/hmac.nim deleted file mode 100644 index da692ac..0000000 --- a/src/blobsets/priv/nimcrypto/hmac.nim +++ /dev/null @@ -1,289 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements HMAC (Keyed-Hashing for Message Authentication) -## [http://www.ietf.org/rfc/rfc2104.txt]. -## -## Module provides two common interfaces for calculating HMAC. -## ``Classic`` method allows to process big chunks of data using limited amount -## of memory, while ``one-line`` method allows you to perform HMAC calculation -## in one line of code. -## -## .. code-block::nim -## import nimcrypto -## -## ## ``Classic`` method of HMAC calculation. -## -## var stringToHmac = "Hello World!" -## var stringHmacKey = "AliceKey" -## let ptrToHmac = cast[ptr byte](addr stringToHmac[0]) -## let ptrHmacKey = cast[ptr byte](addr stringHmacKey[0]) -## let toHmacLen = uint(len(stringToHmac)) -## let hmacKeyLen = uint(len(stringHmacKey)) -## -## # Declare context objects -## var hctx1, hctx2: HMAC[sha256] -## # Initalize HMAC[SHA256] contexts with key `AliceKey`. -## hctx1.init(stringHmacKey) -## hctx2.init(ptrHmacKey, hmacKeyLen) -## # Update HMAC[SHA256] context using data `Hello World!` twice. -## hctx1.update(stringToHmac) -## hctx1.update(stringToHmac) -## # Update HMAC[SHA256] context using data `Hello World!` twice. -## hctx2.update(ptrToHmac, toHmacLen) -## hctx2.update(ptrToHmac, toHmacLen) -## # Print HMAC[SHA256] digest. -## echo $hctx1.finish() -## echo $hctx2.finish() -## # Do not forget to clear contexts. -## hctx1.clear() -## hctx2.clear() -## -## ## ``One-line`` method of HMAC calculation. -## -## # Print HMAC[SHA256] digest of `Hello World!Hello World!` using key -## # `AliceKey`. -## echo $sha256.hmac(stringHmacKey, stringToHmac & stringToHmac) -## -## # Output to stdout must be 3 equal digests: -## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D -## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D -## # 18AF7C8586141A47EAAD416C2B356431D001FAFF3B8C98C80AA108DC971B230D -import hash, utils -from sha2 import Sha2Context -from ripemd import RipemdContext -from keccak import KeccakContext -from blake2 import Blake2Context - -{.deadCodeElim:on.} - -const - MaxHmacBlockSize = 256 - -type - HMAC*[HashType] = object - ## HMAC context object. - mdctx: HashType - opadctx: HashType - -template sizeBlock*(h: HMAC[Sha2Context]): uint = - ## Size of processing block in octets (bytes), while perform HMAC - ## operation using SHA2 algorithms. - cast[uint](h.HashType.sizeBlock) - -template sizeBlock*(h: HMAC[RipemdContext]): uint = - ## Size of processing block in octets (bytes), while perform HMAC - ## operation using RIPEMD algorithms. - cast[uint](h.HashType.sizeBlock) - -template sizeBlock*(h: HMAC[KeccakContext]): uint = - ## Size of processing block in octets (bytes), while perform HMAC - ## operation using KECCAK/SHA3/SHAKE algorithms. - when h.HashType.kind == Keccak or h.HashType.kind == Sha3: - when h.HashType.bits == 224: - 144'u - elif h.HashType.bits == 256: - 136'u - elif h.HashType.bits == 384: - 104'u - elif h.HashType.bits == 512: - 72'u - else: - {.fatal: "Choosen hash primitive is not yet supported!".} - else: - {.fatal: "Choosen hash primitive is not yet supported!".} - -template sizeBlock*(h: HMAC[Blake2Context]): uint = - ## Size of processing block in octets (bytes), while perform HMAC - ## operation using BLAKE2b/BLAKE2s algorithms. - cast[uint](h.HashType.sizeBlock) - -template sizeDigest*(h: HMAC[Sha2Context]): uint = - ## Size of HMAC digest in octets (bytes) using SHA2 algorithms. - cast[uint](h.mdctx.sizeDigest) - -template sizeDigest*(h: HMAC[RipemdContext]): uint = - ## Size of HMAC digest in octets (bytes) using RIPEMD algorithms. - cast[uint](h.mdctx.sizeDigest) - -template sizeDigest*(h: HMAC[KeccakContext]): uint = - ## Size of HMAC digest in octets (bytes) using KECCAK/SHA3/SHAKE - ## algorithms. - cast[uint](h.mdctx.sizeDigest) - -template sizeDigest*(h: HMAC[Blake2Context]): uint = - ## Size of HMAC digest in octets (bytes) using BLAKE2b/BLAKE2s algorithms. - cast[uint](h.mdctx.sizeDigest) - -proc init*[T](hmctx: var HMAC[T], key: ptr byte, ulen: uint) = - ## Initialize HMAC context ``hmctx`` with key using ``key`` and size ``ulen``. - ## - ## ``key`` can be ``nil``. - mixin init, update, finish - var k: array[MaxHmacBlockSize, byte] - var ipad: array[MaxHmacBlockSize, byte] - var opad: array[MaxHmacBlockSize, byte] - const sizeBlock = hmctx.sizeBlock - - hmctx.mdctx = T() - hmctx.opadctx = T() - init(hmctx.opadctx) - - if not isNil(key): - if ulen > sizeBlock: - init(hmctx.mdctx) - update(hmctx.mdctx, key, ulen) - discard finish(hmctx.mdctx, addr k[0], sizeBlock) - else: - if ulen > 0'u: copyMem(addr k[0], key, ulen) - - for i in 0..= hmctx.sizeDigest) - result = finish(hmctx, cast[ptr byte](addr data[0]), ulen) - -proc finish*(hmctx: var HMAC): MDigest[hmctx.HashType.bits] = - ## Finalize HMAC context ``hmctx`` and return calculated digest as ``MDigest`` - ## object. - discard finish(hmctx, cast[ptr byte](addr result.data[0]), - cast[uint](len(result.data))) - -proc hmac*(HashType: typedesc, key: ptr byte, klen: uint, - data: ptr byte, ulen: uint): MDigest[HashType.bits] = - ## Perform HMAC computation with hash algorithm ``HashType`` using key ``key`` - ## of length ``klen`` on data buffer pointed by ``data`` of length ``ulen``. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var stringToHmac = "Hello World!" - ## var stringHmacKey = "AliceKey" - ## let data = cast[ptr byte](addr stringToHmac[0]) - ## let datalen = uint(len(stringToHmac)) - ## let key = cast[ptr byte](addr stringHmacKey[0]) - ## let keylen = uint(len(stringHmacKey)) - ## # Print HMAC[SHA256](key = "AliceKey", data = "Hello World!") - ## echo sha256.hmac(key, keylen, data, datalen) - ## # Print HMAC[SHA512](key = "AliceKey", data = "Hello World!") - ## echo sha512.hmac(key, keylen, data, datalen) - ## # Print HMAC[KECCAK256](key = "AliceKey", data = "Hello World!") - ## echo keccak256.hmac(key, keylen, data, datalen) - ## # Print HMAC[RIPEMD160](key = "AliceKey", data = "Hello World!") - ## echo ripemd160.hmac(key, keylen, data, datalen) - var ctx: HMAC[HashType] - ctx.init(key, klen) - ctx.update(data, ulen) - result = ctx.finish() - ctx.clear() - -proc hmac*[A, B](HashType: typedesc, key: openarray[A], - data: openarray[B], - ostart: int = 0, ofinish: int = -1): MDigest[HashType.bits] = - ## Perform HMAC computation with hash algorithm ``HashType`` using key ``key`` - ## of data ``data``, in slice ``[ostart, ofinish]``, both ``ostart`` and - ## ``ofinish`` are inclusive. - ## - ## .. code-block::nim - ## import nimcrypto - ## - ## var stringToHmac = "Hello World!" - ## var stringHmacKey = "AliceKey" - ## # Print HMAC[SHA256] digest of whole string `Hello World!` using - ## # key `AliceKey`. - ## echo sha256.hmac(stringHmacKey, stringToHmac) - ## # Print HMAC[SHA256] digest of `Hello` using key `AliceKey`. - ## echo sha256.hmac(stringHmacKey, stringToHmac, ofinish = 4) - ## # Print HMAC[SHA256] digest of `World!` using key `AliceKey`. - ## echo sha256.hmac(stringHmacKey, stringToHmac, ostart = 6) - ## # Print HMAC[SHA256] digest of constant `Hello` using constant key - ## # `AliceKey`. - ## echo sha256.hmac("AliceKey", "Hello") - ## # Print HMAC[SHA256] digest of constant `World!` using constant key - ## # `AliceKey` - ## echo sha256.hmac("AliceKey", "World!") - var ctx: HMAC[HashType] - let so = if ostart < 0: (len(data) + ostart) else: ostart - let eo = if ofinish < 0: (len(data) + ofinish) else: ofinish - let length = (eo - so + 1) * sizeof(B) - if len(key) == 0: - ctx.init(nil, 0) - else: - ctx.init(cast[ptr byte](unsafeAddr key[0]), - cast[uint](sizeof(A) * len(key))) - if length <= 0: - result = ctx.finish() - else: - ctx.update(cast[ptr byte](unsafeAddr data[so]), cast[uint](length)) - result = ctx.finish() - ctx.clear() diff --git a/src/blobsets/priv/nimcrypto/keccak.nim b/src/blobsets/priv/nimcrypto/keccak.nim deleted file mode 100644 index df11715..0000000 --- a/src/blobsets/priv/nimcrypto/keccak.nim +++ /dev/null @@ -1,324 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2018 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements SHA3 (Secure Hash Algorithm 3) set of cryptographic -## hash functions designed by Guido Bertoni, Joan Daemen, Michaël Peeters and -## Gilles Van Assche. -## -## This module supports SHA3-224/256/384/512 and SHAKE-128/256. -## -## Tests for SHA3-225/256/384/512 made according to -## [https://www.di-mgt.com.au/sha_testvectors.html]. -## Test for SHAKE-128/256 made according to -## [https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values#aHashing] -## 0bit and 1600bit test vectors used. - -import hash, utils - -{.deadCodeElim:on.} - -const RNDC = [ - 0x0000000000000001'u64, 0x0000000000008082'u64, 0x800000000000808A'u64, - 0x8000000080008000'u64, 0x000000000000808B'u64, 0x0000000080000001'u64, - 0x8000000080008081'u64, 0x8000000000008009'u64, 0x000000000000008A'u64, - 0x0000000000000088'u64, 0x0000000080008009'u64, 0x000000008000000A'u64, - 0x000000008000808B'u64, 0x800000000000008B'u64, 0x8000000000008089'u64, - 0x8000000000008003'u64, 0x8000000000008002'u64, 0x8000000000000080'u64, - 0x000000000000800A'u64, 0x800000008000000A'u64, 0x8000000080008081'u64, - 0x8000000000008080'u64, 0x0000000080000001'u64, 0x8000000080008008'u64 -] - -type - KeccakKind* = enum - Sha3, Keccak, Shake - - KeccakContext*[bits: static[int], - kind: static[KeccakKind]] = object - q: array[25, uint64] - pt: int - - keccak224* = KeccakContext[224, Keccak] - keccak256* = KeccakContext[256, Keccak] - keccak384* = KeccakContext[384, Keccak] - keccak512* = KeccakContext[512, Keccak] - sha3_224* = KeccakContext[224, Sha3] - sha3_256* = KeccakContext[256, Sha3] - sha3_384* = KeccakContext[384, Sha3] - sha3_512* = KeccakContext[512, Sha3] - shake128* = KeccakContext[128, Shake] - shake256* = KeccakContext[256, Shake] - keccak* = keccak224 | keccak256 | keccak384 | keccak512 | - sha3_224 | sha3_256 | sha3_384 | sha3_512 - -template THETA1(a, b, c: untyped) = - (a)[(c)] = (b)[(c)] xor (b)[(c) + 5] xor (b)[(c) + 10] xor - (b)[(c) + 15] xor (b)[(c) + 20] - -template THETA2(a, b, c: untyped) = - (a) = (b)[((c) + 4) mod 5] xor ROL(cast[uint64]((b)[((c) + 1) mod 5]), 1) - -template THETA3(a, b) = - (a)[(b)] = (a)[(b)] xor t - (a)[(b) + 5] = (a)[(b) + 5] xor t - (a)[(b) + 10] = (a)[(b) + 10] xor t - (a)[(b) + 15] = (a)[(b) + 15] xor t - (a)[(b) + 20] = (a)[(b) + 20] xor t - -template RHOPI(a, b, c, d, e) = - (a)[0] = (b)[(d)] - (b)[(d)] = ROL(cast[uint64](c), e) - (c) = (a)[0] - -template CHI(a, b, c) = - (a)[0] = (b)[(c)] - (a)[1] = (b)[(c) + 1] - (a)[2] = (b)[(c) + 2] - (a)[3] = (b)[(c) + 3] - (a)[4] = (b)[(c) + 4] - (b)[(c)] = (b)[(c)] xor (not((a)[1]) and (a)[2]) - (b)[(c + 1)] = (b)[(c + 1)] xor (not((a)[2]) and (a)[3]) - (b)[(c + 2)] = (b)[(c + 2)] xor (not((a)[3]) and (a)[4]) - (b)[(c + 3)] = (b)[(c + 3)] xor (not((a)[4]) and (a)[0]) - (b)[(c + 4)] = (b)[(c + 4)] xor (not((a)[0]) and (a)[1]) - -template KECCAKROUND(a, b, c, r) = - THETA1((b), (a), 0) - THETA1((b), (a), 1) - THETA1((b), (a), 2) - THETA1((b), (a), 3) - THETA1((b), (a), 4) - - THETA2((c), (b), 0) - THETA3((a), 0) - THETA2((c), (b), 1) - THETA3((a), 1) - THETA2((c), (b), 2) - THETA3((a), 2) - THETA2((c), (b), 3) - THETA3((a), 3) - THETA2((c), (b), 4) - THETA3((a), 4) - - (c) = (a)[1] - RHOPI((b), (a), (c), 10, 1) - RHOPI((b), (a), (c), 7, 3) - RHOPI((b), (a), (c), 11, 6) - RHOPI((b), (a), (c), 17, 10) - RHOPI((b), (a), (c), 18, 15) - RHOPI((b), (a), (c), 3, 21) - RHOPI((b), (a), (c), 5, 28) - RHOPI((b), (a), (c), 16, 36) - RHOPI((b), (a), (c), 8, 45) - RHOPI((b), (a), (c), 21, 55) - RHOPI((b), (a), (c), 24, 2) - RHOPI((b), (a), (c), 4, 14) - RHOPI((b), (a), (c), 15, 27) - RHOPI((b), (a), (c), 23, 41) - RHOPI((b), (a), (c), 19, 56) - RHOPI((b), (a), (c), 13, 8) - RHOPI((b), (a), (c), 12, 25) - RHOPI((b), (a), (c), 2, 43) - RHOPI((b), (a), (c), 20, 62) - RHOPI((b), (a), (c), 14, 18) - RHOPI((b), (a), (c), 22, 39) - RHOPI((b), (a), (c), 9, 61) - RHOPI((b), (a), (c), 6, 20) - RHOPI((b), (a), (c), 1, 44) - - # Chi - CHI((b), (a), 0) - CHI((b), (a), 5) - CHI((b), (a), 10) - CHI((b), (a), 15) - CHI((b), (a), 20) - - (a)[0] = (a)[0] xor RNDC[(r)] - -proc keccakTransform(st: var array[25, uint64]) = - var bc: array[5, uint64] - var t: uint64 - - st[0] = BSWAP(st[0]) - st[1] = BSWAP(st[1]) - st[2] = BSWAP(st[2]) - st[3] = BSWAP(st[3]) - st[4] = BSWAP(st[4]) - st[5] = BSWAP(st[5]) - st[6] = BSWAP(st[6]) - st[7] = BSWAP(st[7]) - st[8] = BSWAP(st[8]) - st[9] = BSWAP(st[9]) - st[10] = BSWAP(st[10]) - st[11] = BSWAP(st[11]) - st[12] = BSWAP(st[12]) - st[13] = BSWAP(st[13]) - st[14] = BSWAP(st[14]) - st[15] = BSWAP(st[15]) - st[16] = BSWAP(st[16]) - st[17] = BSWAP(st[17]) - st[18] = BSWAP(st[18]) - st[19] = BSWAP(st[19]) - st[20] = BSWAP(st[20]) - st[21] = BSWAP(st[21]) - st[22] = BSWAP(st[22]) - st[23] = BSWAP(st[23]) - st[24] = BSWAP(st[24]) - - KECCAKROUND(st, bc, t, 0) - KECCAKROUND(st, bc, t, 1) - KECCAKROUND(st, bc, t, 2) - KECCAKROUND(st, bc, t, 3) - KECCAKROUND(st, bc, t, 4) - KECCAKROUND(st, bc, t, 5) - KECCAKROUND(st, bc, t, 6) - KECCAKROUND(st, bc, t, 7) - KECCAKROUND(st, bc, t, 8) - KECCAKROUND(st, bc, t, 9) - KECCAKROUND(st, bc, t, 10) - KECCAKROUND(st, bc, t, 11) - KECCAKROUND(st, bc, t, 12) - KECCAKROUND(st, bc, t, 13) - KECCAKROUND(st, bc, t, 14) - KECCAKROUND(st, bc, t, 15) - KECCAKROUND(st, bc, t, 16) - KECCAKROUND(st, bc, t, 17) - KECCAKROUND(st, bc, t, 18) - KECCAKROUND(st, bc, t, 19) - KECCAKROUND(st, bc, t, 20) - KECCAKROUND(st, bc, t, 21) - KECCAKROUND(st, bc, t, 22) - KECCAKROUND(st, bc, t, 23) - - st[0] = BSWAP(st[0]) - st[1] = BSWAP(st[1]) - st[2] = BSWAP(st[2]) - st[3] = BSWAP(st[3]) - st[4] = BSWAP(st[4]) - st[5] = BSWAP(st[5]) - st[6] = BSWAP(st[6]) - st[7] = BSWAP(st[7]) - st[8] = BSWAP(st[8]) - st[9] = BSWAP(st[9]) - st[10] = BSWAP(st[10]) - st[11] = BSWAP(st[11]) - st[12] = BSWAP(st[12]) - st[13] = BSWAP(st[13]) - st[14] = BSWAP(st[14]) - st[15] = BSWAP(st[15]) - st[16] = BSWAP(st[16]) - st[17] = BSWAP(st[17]) - st[18] = BSWAP(st[18]) - st[19] = BSWAP(st[19]) - st[20] = BSWAP(st[20]) - st[21] = BSWAP(st[21]) - st[22] = BSWAP(st[22]) - st[23] = BSWAP(st[23]) - st[24] = BSWAP(st[24]) - -template sizeDigest*(ctx: KeccakContext): uint = - (ctx.bits div 8) - -template sizeBlock*(ctx: KeccakContext): uint = - (200) - -template rsize(ctx: KeccakContext): int = - 200 - 2 * (ctx.bits div 8) - -template sizeDigest*(r: typedesc[keccak | shake128 | shake256]): int = - when r is shake128: - (16) - elif r is keccak224 or r is sha3_224: - (28) - elif r is keccak256 or r is sha3_256 or r is shake256: - (32) - elif r is keccak384 or r is sha3_384: - (48) - elif r is keccak512 or r is sha3_512: - (64) - -template sizeBlock*(r: typedesc[keccak | shake128 | shake256]): int = - (200) - -proc init*(ctx: var KeccakContext) = - burnMem(ctx) - -proc clear*(ctx: var KeccakContext) {.inline.} = - ctx.init() - -proc update*(ctx: var KeccakContext, data: ptr byte, ulen: uint) = - var j = ctx.pt - var s = cast[ptr UncheckedArray[byte]](data) - var d = cast[ptr UncheckedArray[byte]](addr ctx.q[0]) - if ulen > 0'u: - for i in 0..(ulen - 1): - d[j] = d[j] xor s[i] - inc(j) - if j >= ctx.rsize: - keccakTransform(ctx.q) - j = 0 - ctx.pt = j - -proc update*[T: bchar](ctx: var KeccakContext, data: openarray[T]) = - if len(data) == 0: - update(ctx, nil, 0'u) - else: - update(ctx, cast[ptr byte](unsafeAddr data[0]), cast[uint](len(data))) - -proc finalizeKeccak(ctx: var KeccakContext) = - var d = cast[ptr UncheckedArray[byte]](addr ctx.q[0]) - when ctx.kind == Sha3: - d[ctx.pt] = d[ctx.pt] xor 0x06'u8 - else: - d[ctx.pt] = d[ctx.pt] xor 0x01'u8 - d[ctx.rsize - 1] = d[ctx.rsize - 1] xor 0x80'u8 - keccakTransform(ctx.q) - -proc xof*(ctx: var KeccakContext) = - when ctx.kind != Shake: - {.error: "Only `Shake128` and `Shake256` types are supported".} - assert(ctx.kind == Shake) - var d = cast[ptr UncheckedArray[byte]](addr ctx.q[0]) - d[ctx.pt] = d[ctx.pt] xor 0x1F'u8 - d[ctx.rsize - 1] = d[ctx.rsize - 1] xor 0x80'u8 - keccakTransform(ctx.q) - ctx.pt = 0 - -proc output*(ctx: var KeccakContext, data: ptr byte, ulen: uint): uint = - when ctx.kind != Shake: - {.error: "Only `Shake128` and `Shake256` types are supported".} - var j = ctx.pt - var s = cast[ptr UncheckedArray[byte]](addr ctx.q[0]) - var d = cast[ptr UncheckedArray[byte]](data) - - if ulen > 0'u: - for i in 0..(ulen - 1): - if j >= ctx.rsize: - keccakTransform(ctx.q) - j = 0 - d[i] = s[j] - inc(j) - ctx.pt = j - result = ulen - -proc finish*(ctx: var KeccakContext, data: ptr byte, ulen: uint): uint = - finalizeKeccak(ctx) - var d = cast[ptr UncheckedArray[byte]](data) - var s = cast[ptr UncheckedArray[byte]](addr ctx.q[0]) - if ulen >= ctx.sizeDigest: - for i in 0..(ctx.sizeDigest - 1): - d[i] = s[i] - result = ctx.sizeDigest - -proc finish*(ctx: var KeccakContext): MDigest[ctx.bits] = - discard finish(ctx, cast[ptr byte](addr result.data[0]), - cast[uint](len(result.data))) - -proc finish*[T: bchar](ctx: var KeccakContext, data: var openarray[T]) = - assert(cast[uint](len(data)) >= ctx.sizeDigest) - discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data))) diff --git a/src/blobsets/priv/nimcrypto/pbkdf2.nim b/src/blobsets/priv/nimcrypto/pbkdf2.nim deleted file mode 100644 index b5a2c42..0000000 --- a/src/blobsets/priv/nimcrypto/pbkdf2.nim +++ /dev/null @@ -1,67 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2018 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements PBKDF2 (Password-Based Key Derivation Function 2) -## [https://tools.ietf.org/html/rfc2898#section-5.2] -## -## Tests for PBKDF2-HMAC-SHA224/256/384/512 made according to -## [https://github.com/Anti-weakpasswords/PBKDF2-Test-Vectors/releases] - -import hmac - -proc pbkdf2*[T](ctx: var HMAC[T], password: string, salt: string, c: int, - output: var openarray[byte], outlen: int = -1): int = - ## Calculate PBKDF2 result using HMAC algorithm `ctx`. - ## - ## ``ctx`` - HMAC[T] context - ## ``password`` - password string - ## ``salt`` - salt string - ## ``c`` - number of iterations - ## ``output`` - array of bytes where result will be stored. - ## ``outlen`` - length of bytes to be stored (-1 default, whole `output`) - ## - ## Returns number of bytes stored on success, or 0 on error. - mixin init, update, finish - var - counter: array[4, byte] - work: array[ctx.sizeDigest, byte] - md: array[ctx.sizeDigest, byte] - ctr: uint32 - glength: int - olength: int - bytesWrite: int - if len(output) > 0xFFFF_FFFF: # (2^32 - 1) - return 0 - let pwd = cast[seq[byte]](password) - let slt = cast[seq[byte]](salt) - ctr = 1 - glength = 0 - olength = if outlen == -1: len(output) else: outlen - while glength < olength: - counter[0] = byte((ctr shr 24) and 0xFF) - counter[1] = byte((ctr shr 16) and 0xFF) - counter[2] = byte((ctr shr 8) and 0xFF) - counter[3] = byte(ctr and 0xFF) - ctx.init(pwd) - ctx.update(slt) - ctx.update(counter) - discard ctx.finish(md) - work = md - for i in 1.. 10: - ENC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKe, 10) - ENC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKe, 11) - if ctx.Nr > 12: - ENC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKe, 12) - ENC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKe, 13) - - let offset = (ctx.Nr shl 2).uint32 - - s0 = (Te4[(t0 shr 24)] and 0xFF000000'u32) xor - (Te4[(t1 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Te4[(t2 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Te4[t3 and 0xFF] and 0x000000FF'u32) xor - ctx.RKe[offset] - s1 = (Te4[(t1 shr 24)] and 0xFF000000'u32) xor - (Te4[(t2 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Te4[(t3 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Te4[t0 and 0xFF] and 0x000000FF'u32) xor - ctx.RKe[offset + 1] - s2 = (Te4[(t2 shr 24)] and 0xFF000000'u32) xor - (Te4[(t3 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Te4[(t0 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Te4[t1 and 0xFF] and 0x000000FF'u32) xor - ctx.RKe[offset + 2] - s3 = (Te4[(t3 shr 24)] and 0xFF000000'u32) xor - (Te4[(t0 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Te4[(t1 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Te4[t2 and 0xFF] and 0x000000FF'u32) xor - ctx.RKe[offset + 3] - - PUTU32(oup, 0, s0) - PUTU32(oup, 4, s1) - PUTU32(oup, 8, s2) - PUTU32(oup, 12, s3) - -proc rijndaelDecrypt*(ctx: var RijndaelContext, inp: ptr byte, - oup: ptr byte) = - var t0, t1, t2, t3: uint32 - - var s0 = GETU32(inp, 0) xor ctx.RKd[0] - var s1 = GETU32(inp, 4) xor ctx.RKd[1] - var s2 = GETU32(inp, 8) xor ctx.RKd[2] - var s3 = GETU32(inp, 12) xor ctx.RKd[3] - - DEC_ROUND(t0, t1, t2 ,t3, s0, s1, s2, s3, ctx.RKd, 1) - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 2) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 3) - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 4) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 5) - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 6) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 7) - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 8) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 9) - if ctx.Nr > 10: - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 10) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 11) - if ctx.Nr > 12: - DEC_ROUND(s0, s1, s2, s3, t0, t1, t2, t3, ctx.RKd, 12) - DEC_ROUND(t0, t1, t2, t3, s0, s1, s2, s3, ctx.RKd, 13) - - let offset = (ctx.Nr shl 2).uint32 - - s0 = (Td4[(t0 shr 24)] and 0xFF000000'u32) xor - (Td4[(t3 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Td4[(t2 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Td4[t1 and 0xFF] and 0x000000FF'u32) xor - ctx.RKd[offset] - s1 = (Td4[(t1 shr 24)] and 0xFF000000'u32) xor - (Td4[(t0 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Td4[(t3 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Td4[t2 and 0xFF] and 0x000000FF'u32) xor - ctx.RKd[offset + 1] - s2 = (Td4[(t2 shr 24)] and 0xFF000000'u32) xor - (Td4[(t1 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Td4[(t0 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Td4[t3 and 0xFF] and 0x000000FF'u32) xor - ctx.RKd[offset + 2] - s3 = (Td4[(t3 shr 24)] and 0xFF000000'u32) xor - (Td4[(t2 shr 16) and 0xFF] and 0x00FF0000'u32) xor - (Td4[(t1 shr 8) and 0xFF] and 0x0000FF00'u32) xor - (Td4[t0 and 0xFF] and 0x000000FF'u32) xor - ctx.RKd[offset + 3] - - PUTU32(oup, 0, s0) - PUTU32(oup, 4, s1) - PUTU32(oup, 8, s2) - PUTU32(oup, 12, s3) - -proc initRijndaelContext*(ctx: var RijndaelContext, N: int, key: ptr byte) = - ctx.Nr = rijndaelKeySetupDec(ctx, N, key) - -template sizeKey*(ctx: RijndaelContext): int = - (ctx.bits div 8) - -template sizeBlock*(ctx: RijndaelContext): int = - (16) - -template sizeKey*(r: typedesc[rijndael]): int = - when r is aes128 or r is rijndael128: - (16) - elif r is aes192 or r is rijndael192: - (24) - elif r is aes256 or r is rijndael256: - (32) - -template sizeBlock*(r: typedesc[rijndael]): int = - (16) - -proc init*(ctx: var RijndaelContext, key: ptr byte, nkey: int = 0) {.inline.} = - ctx.Nr = rijndaelKeySetupDec(ctx, ctx.bits, key) - -proc init*(ctx: var RijndaelContext, key: openarray[byte]) {.inline.} = - assert(len(key) >= ctx.sizeKey) - ctx.Nr = rijndaelKeySetupDec(ctx, ctx.bits, unsafeAddr key[0]) - -proc clear*(ctx: var RijndaelContext) {.inline.} = - burnMem(ctx) - -proc encrypt*(ctx: var RijndaelContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - rijndaelEncrypt(ctx, inbytes, outbytes) - -proc decrypt*(ctx: var RijndaelContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - rijndaelDecrypt(ctx, inbytes, outbytes) - -proc encrypt*(ctx: var RijndaelContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - rijndaelEncrypt(ctx, unsafeAddr input[0], addr output[0]) - -proc decrypt*(ctx: var RijndaelContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - rijndaelDecrypt(ctx, unsafeAddr input[0], addr output[0]) diff --git a/src/blobsets/priv/nimcrypto/ripemd.nim b/src/blobsets/priv/nimcrypto/ripemd.nim deleted file mode 100644 index 93c19cc..0000000 --- a/src/blobsets/priv/nimcrypto/ripemd.nim +++ /dev/null @@ -1,750 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016-2018 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements RIPEMD set of cryptographic hash functions, -## designed by Hans Dobbertin, Antoon Bosselaers and Bart Preneel. -## [http://www.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf] -## -## This module is Nim adoptation of original C source code by -## Antoon Bosselaers. -## [https://homes.esat.kuleuven.be/~bosselae/ripemd160/ps/AB-9601/rmd160.c] -## -## This module includes support of RIPEMD-128/160/256/320. -## -## Tests made according to official test vectors -## [https://homes.esat.kuleuven.be/~bosselae/ripemd160.html]. - -import hash, utils - -type - RipemdContext*[bits: static[int]] = object - count: array[2, uint32] - state: array[bits div 32, uint32] - buffer: array[64, byte] - - ripemd128* = RipemdContext[128] - ripemd160* = RipemdContext[160] - ripemd256* = RipemdContext[256] - ripemd320* = RipemdContext[320] - ripemd* = ripemd128 | ripemd160 | ripemd256 | ripemd320 - -# Five basic functions F(), G() and H() -template F(x, y, z: untyped): untyped = - # x^y^z - ((x) xor (y) xor (z)) - -template G(x, y, z: untyped): untyped = - # (x&y)|(~x&z) - (((x) and (y)) or (not (x) and (z))) - -template H(x, y, z: untyped): untyped = - # (x|~y)^z - (((x) or not (y)) xor (z)) - -template I(x, y, z: untyped): untyped = - # (x&z)|(y&~z) - (((x) and (z)) or ((y) and not (z))) - -template J(x, y, z: untyped): untyped = - # x^(y|~z) - ((x) xor ((y) or not (z))) - -# Eight basic operations FF() through III() for 128 and 256 bits -template FF128(a, b, c, d, x, s: untyped): void = - (a) = (a) + F((b), (c), (d)) + (x) - (a) = ROL(cast[uint32](a), (s)) - -template GG128(a, b, c, d, x, s: untyped): void = - (a) = (a) + G((b), (c), (d)) + (x) + 0x5A827999'u32 - (a) = ROL(cast[uint32](a), (s)) - -template HH128(a, b, c, d, x, s: untyped): void = - (a) = (a) + H((b), (c), (d)) + (x) + 0x6ED9EBA1'u32 - (a) = ROL(cast[uint32](a), (s)) - -template II128(a, b, c, d, x, s: untyped): void = - (a) = (a) + I((b), (c), (d)) + (x) + 0x8F1BBCDC'u32 - (a) = ROL(cast[uint32](a), (s)) - -template FFF128(a, b, c, d, x, s: untyped): void = - (a) = (a) + F((b), (c), (d)) + (x) - (a) = ROL(cast[uint32](a), (s)) - -template GGG128(a, b, c, d, x, s: untyped): void = - (a) = (a) + G((b), (c), (d)) + (x) + 0x6D703EF3'u32 - (a) = ROL(cast[uint32](a), (s)) - -template HHH128(a, b, c, d, x, s: untyped): void = - (a) = (a) + H((b), (c), (d)) + (x) + 0x5C4DD124'u32 - (a) = ROL(cast[uint32](a), (s)) - -template III128(a, b, c, d, x, s: untyped): void = - (a) = (a) + I((b), (c), (d)) + (x) + 0x50A28BE6'u32 - (a) = ROL((a), (s)) - -# Ten basic operations FF() through III() for 160 and 320 bits -template FF160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + F((b), (c), (d)) + (x) - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template GG160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + G((b), (c), (d)) + (x) + 0x5A827999'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template HH160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + H((b), (c), (d)) + (x) + 0x6ED9EBA1'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template II160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + I((b), (c), (d)) + (x) + 0x8F1BBCDC'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template JJ160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + J((b), (c), (d)) + (x) + 0xA953FD4E'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template FFF160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + F((b), (c), (d)) + (x) - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template GGG160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + G((b), (c), (d)) + (x) + 0x7A6D76E9'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template HHH160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + H((b), (c), (d)) + (x) + 0x6D703EF3'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template III160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + I((b), (c), (d)) + (x) + 0x5C4DD124'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template JJJ160(a, b, c, d, e, x, s: untyped): void = - (a) = (a) + J((b), (c), (d)) + (x) + 0x50A28BE6'u32 - (a) = ROL(cast[uint32](a), (s)) + (e) - (c) = ROL(cast[uint32](c), 10) - -template LROUND128N1(a, b, c, d, x): void = - FF128(a, b, c, d, x[ 0], 11) - FF128(d, a, b, c, x[ 1], 14) - FF128(c, d, a, b, x[ 2], 15) - FF128(b, c, d, a, x[ 3], 12) - FF128(a, b, c, d, x[ 4], 5) - FF128(d, a, b, c, x[ 5], 8) - FF128(c, d, a, b, x[ 6], 7) - FF128(b, c, d, a, x[ 7], 9) - FF128(a, b, c, d, x[ 8], 11) - FF128(d, a, b, c, x[ 9], 13) - FF128(c, d, a, b, x[10], 14) - FF128(b, c, d, a, x[11], 15) - FF128(a, b, c, d, x[12], 6) - FF128(d, a, b, c, x[13], 7) - FF128(c, d, a, b, x[14], 9) - FF128(b, c, d, a, x[15], 8) - -template LROUND128N2(a, b, c, d, x): void = - GG128(a, b, c, d, x[ 7], 7) - GG128(d, a, b, c, x[ 4], 6) - GG128(c, d, a, b, x[13], 8) - GG128(b, c, d, a, x[ 1], 13) - GG128(a, b, c, d, x[10], 11) - GG128(d, a, b, c, x[ 6], 9) - GG128(c, d, a, b, x[15], 7) - GG128(b, c, d, a, x[ 3], 15) - GG128(a, b, c, d, x[12], 7) - GG128(d, a, b, c, x[ 0], 12) - GG128(c, d, a, b, x[ 9], 15) - GG128(b, c, d, a, x[ 5], 9) - GG128(a, b, c, d, x[ 2], 11) - GG128(d, a, b, c, x[14], 7) - GG128(c, d, a, b, x[11], 13) - GG128(b, c, d, a, x[ 8], 12) - -template LROUND128N3(a, b, c, d, x): void = - HH128(a, b, c, d, x[ 3], 11) - HH128(d, a, b, c, x[10], 13) - HH128(c, d, a, b, x[14], 6) - HH128(b, c, d, a, x[ 4], 7) - HH128(a, b, c, d, x[ 9], 14) - HH128(d, a, b, c, x[15], 9) - HH128(c, d, a, b, x[ 8], 13) - HH128(b, c, d, a, x[ 1], 15) - HH128(a, b, c, d, x[ 2], 14) - HH128(d, a, b, c, x[ 7], 8) - HH128(c, d, a, b, x[ 0], 13) - HH128(b, c, d, a, x[ 6], 6) - HH128(a, b, c, d, x[13], 5) - HH128(d, a, b, c, x[11], 12) - HH128(c, d, a, b, x[ 5], 7) - HH128(b, c, d, a, x[12], 5) - -template LROUND128N4(a, b, c, d, x): void = - II128(a, b, c, d, x[ 1], 11) - II128(d, a, b, c, x[ 9], 12) - II128(c, d, a, b, x[11], 14) - II128(b, c, d, a, x[10], 15) - II128(a, b, c, d, x[ 0], 14) - II128(d, a, b, c, x[ 8], 15) - II128(c, d, a, b, x[12], 9) - II128(b, c, d, a, x[ 4], 8) - II128(a, b, c, d, x[13], 9) - II128(d, a, b, c, x[ 3], 14) - II128(c, d, a, b, x[ 7], 5) - II128(b, c, d, a, x[15], 6) - II128(a, b, c, d, x[14], 8) - II128(d, a, b, c, x[ 5], 6) - II128(c, d, a, b, x[ 6], 5) - II128(b, c, d, a, x[ 2], 12) - -template RROUND128N1(a, b, c, d, x): void = - III128(a, b, c, d, x[ 5], 8) - III128(d, a, b, c, x[14], 9) - III128(c, d, a, b, x[ 7], 9) - III128(b, c, d, a, x[ 0], 11) - III128(a, b, c, d, x[ 9], 13) - III128(d, a, b, c, x[ 2], 15) - III128(c, d, a, b, x[11], 15) - III128(b, c, d, a, x[ 4], 5) - III128(a, b, c, d, x[13], 7) - III128(d, a, b, c, x[ 6], 7) - III128(c, d, a, b, x[15], 8) - III128(b, c, d, a, x[ 8], 11) - III128(a, b, c, d, x[ 1], 14) - III128(d, a, b, c, x[10], 14) - III128(c, d, a, b, x[ 3], 12) - III128(b, c, d, a, x[12], 6) - -template RROUND128N2(a, b, c, d, x): void = - HHH128(a, b, c, d, x[ 6], 9) - HHH128(d, a, b, c, x[11], 13) - HHH128(c, d, a, b, x[ 3], 15) - HHH128(b, c, d, a, x[ 7], 7) - HHH128(a, b, c, d, x[ 0], 12) - HHH128(d, a, b, c, x[13], 8) - HHH128(c, d, a, b, x[ 5], 9) - HHH128(b, c, d, a, x[10], 11) - HHH128(a, b, c, d, x[14], 7) - HHH128(d, a, b, c, x[15], 7) - HHH128(c, d, a, b, x[ 8], 12) - HHH128(b, c, d, a, x[12], 7) - HHH128(a, b, c, d, x[ 4], 6) - HHH128(d, a, b, c, x[ 9], 15) - HHH128(c, d, a, b, x[ 1], 13) - HHH128(b, c, d, a, x[ 2], 11) - -template RROUND128N3(a, b, c, d, x): void = - GGG128(a, b, c, d, x[15], 9) - GGG128(d, a, b, c, x[ 5], 7) - GGG128(c, d, a, b, x[ 1], 15) - GGG128(b, c, d, a, x[ 3], 11) - GGG128(a, b, c, d, x[ 7], 8) - GGG128(d, a, b, c, x[14], 6) - GGG128(c, d, a, b, x[ 6], 6) - GGG128(b, c, d, a, x[ 9], 14) - GGG128(a, b, c, d, x[11], 12) - GGG128(d, a, b, c, x[ 8], 13) - GGG128(c, d, a, b, x[12], 5) - GGG128(b, c, d, a, x[ 2], 14) - GGG128(a, b, c, d, x[10], 13) - GGG128(d, a, b, c, x[ 0], 13) - GGG128(c, d, a, b, x[ 4], 7) - GGG128(b, c, d, a, x[13], 5) - -template RROUND128N4(a, b, c, d, x): void = - FFF128(a, b, c, d, x[ 8], 15) - FFF128(d, a, b, c, x[ 6], 5) - FFF128(c, d, a, b, x[ 4], 8) - FFF128(b, c, d, a, x[ 1], 11) - FFF128(a, b, c, d, x[ 3], 14) - FFF128(d, a, b, c, x[11], 14) - FFF128(c, d, a, b, x[15], 6) - FFF128(b, c, d, a, x[ 0], 14) - FFF128(a, b, c, d, x[ 5], 6) - FFF128(d, a, b, c, x[12], 9) - FFF128(c, d, a, b, x[ 2], 12) - FFF128(b, c, d, a, x[13], 9) - FFF128(a, b, c, d, x[ 9], 12) - FFF128(d, a, b, c, x[ 7], 5) - FFF128(c, d, a, b, x[10], 15) - FFF128(b, c, d, a, x[14], 8) - -template LROUND160N1(a, b, c, d, e, x): void = - FF160(a, b, c, d, e, x[ 0], 11) - FF160(e, a, b, c, d, x[ 1], 14) - FF160(d, e, a, b, c, x[ 2], 15) - FF160(c, d, e, a, b, x[ 3], 12) - FF160(b, c, d, e, a, x[ 4], 5) - FF160(a, b, c, d, e, x[ 5], 8) - FF160(e, a, b, c, d, x[ 6], 7) - FF160(d, e, a, b, c, x[ 7], 9) - FF160(c, d, e, a, b, x[ 8], 11) - FF160(b, c, d, e, a, x[ 9], 13) - FF160(a, b, c, d, e, x[10], 14) - FF160(e, a, b, c, d, x[11], 15) - FF160(d, e, a, b, c, x[12], 6) - FF160(c, d, e, a, b, x[13], 7) - FF160(b, c, d, e, a, x[14], 9) - FF160(a, b, c, d, e, x[15], 8) - -template LROUND160N2(a, b, c, d, e, x): void = - GG160(e, a, b, c, d, x[ 7], 7) - GG160(d, e, a, b, c, x[ 4], 6) - GG160(c, d, e, a, b, x[13], 8) - GG160(b, c, d, e, a, x[ 1], 13) - GG160(a, b, c, d, e, x[10], 11) - GG160(e, a, b, c, d, x[ 6], 9) - GG160(d, e, a, b, c, x[15], 7) - GG160(c, d, e, a, b, x[ 3], 15) - GG160(b, c, d, e, a, x[12], 7) - GG160(a, b, c, d, e, x[ 0], 12) - GG160(e, a, b, c, d, x[ 9], 15) - GG160(d, e, a, b, c, x[ 5], 9) - GG160(c, d, e, a, b, x[ 2], 11) - GG160(b, c, d, e, a, x[14], 7) - GG160(a, b, c, d, e, x[11], 13) - GG160(e, a, b, c, d, x[ 8], 12) - -template LROUND160N3(a, b, c, d, e, x): void = - HH160(d, e, a, b, c, x[ 3], 11) - HH160(c, d, e, a, b, x[10], 13) - HH160(b, c, d, e, a, x[14], 6) - HH160(a, b, c, d, e, x[ 4], 7) - HH160(e, a, b, c, d, x[ 9], 14) - HH160(d, e, a, b, c, x[15], 9) - HH160(c, d, e, a, b, x[ 8], 13) - HH160(b, c, d, e, a, x[ 1], 15) - HH160(a, b, c, d, e, x[ 2], 14) - HH160(e, a, b, c, d, x[ 7], 8) - HH160(d, e, a, b, c, x[ 0], 13) - HH160(c, d, e, a, b, x[ 6], 6) - HH160(b, c, d, e, a, x[13], 5) - HH160(a, b, c, d, e, x[11], 12) - HH160(e, a, b, c, d, x[ 5], 7) - HH160(d, e, a, b, c, x[12], 5) - -template LROUND160N4(a, b, c, d, e, x): void = - II160(c, d, e, a, b, x[ 1], 11) - II160(b, c, d, e, a, x[ 9], 12) - II160(a, b, c, d, e, x[11], 14) - II160(e, a, b, c, d, x[10], 15) - II160(d, e, a, b, c, x[ 0], 14) - II160(c, d, e, a, b, x[ 8], 15) - II160(b, c, d, e, a, x[12], 9) - II160(a, b, c, d, e, x[ 4], 8) - II160(e, a, b, c, d, x[13], 9) - II160(d, e, a, b, c, x[ 3], 14) - II160(c, d, e, a, b, x[ 7], 5) - II160(b, c, d, e, a, x[15], 6) - II160(a, b, c, d, e, x[14], 8) - II160(e, a, b, c, d, x[ 5], 6) - II160(d, e, a, b, c, x[ 6], 5) - II160(c, d, e, a, b, x[ 2], 12) - -template LROUND160N5(a, b, c, d, e, x): void = - JJ160(b, c, d, e, a, x[ 4], 9) - JJ160(a, b, c, d, e, x[ 0], 15) - JJ160(e, a, b, c, d, x[ 5], 5) - JJ160(d, e, a, b, c, x[ 9], 11) - JJ160(c, d, e, a, b, x[ 7], 6) - JJ160(b, c, d, e, a, x[12], 8) - JJ160(a, b, c, d, e, x[ 2], 13) - JJ160(e, a, b, c, d, x[10], 12) - JJ160(d, e, a, b, c, x[14], 5) - JJ160(c, d, e, a, b, x[ 1], 12) - JJ160(b, c, d, e, a, x[ 3], 13) - JJ160(a, b, c, d, e, x[ 8], 14) - JJ160(e, a, b, c, d, x[11], 11) - JJ160(d, e, a, b, c, x[ 6], 8) - JJ160(c, d, e, a, b, x[15], 5) - JJ160(b, c, d, e, a, x[13], 6) - -template RROUND160N1(a, b, c, d, e, x): void = - JJJ160(a, b, c, d, e, x[ 5], 8) - JJJ160(e, a, b, c, d, x[14], 9) - JJJ160(d, e, a, b, c, x[ 7], 9) - JJJ160(c, d, e, a, b, x[ 0], 11) - JJJ160(b, c, d, e, a, x[ 9], 13) - JJJ160(a, b, c, d, e, x[ 2], 15) - JJJ160(e, a, b, c, d, x[11], 15) - JJJ160(d, e, a, b, c, x[ 4], 5) - JJJ160(c, d, e, a, b, x[13], 7) - JJJ160(b, c, d, e, a, x[ 6], 7) - JJJ160(a, b, c, d, e, x[15], 8) - JJJ160(e, a, b, c, d, x[ 8], 11) - JJJ160(d, e, a, b, c, x[ 1], 14) - JJJ160(c, d, e, a, b, x[10], 14) - JJJ160(b, c, d, e, a, x[ 3], 12) - JJJ160(a, b, c, d, e, x[12], 6) - -template RROUND160N2(a, b, c, d, e, x): void = - III160(e, a, b, c, d, x[ 6], 9) - III160(d, e, a, b, c, x[11], 13) - III160(c, d, e, a, b, x[ 3], 15) - III160(b, c, d, e, a, x[ 7], 7) - III160(a, b, c, d, e, x[ 0], 12) - III160(e, a, b, c, d, x[13], 8) - III160(d, e, a, b, c, x[ 5], 9) - III160(c, d, e, a, b, x[10], 11) - III160(b, c, d, e, a, x[14], 7) - III160(a, b, c, d, e, x[15], 7) - III160(e, a, b, c, d, x[ 8], 12) - III160(d, e, a, b, c, x[12], 7) - III160(c, d, e, a, b, x[ 4], 6) - III160(b, c, d, e, a, x[ 9], 15) - III160(a, b, c, d, e, x[ 1], 13) - III160(e, a, b, c, d, x[ 2], 11) - -template RROUND160N3(a, b, c, d, e, x): void = - HHH160(d, e, a, b, c, x[15], 9) - HHH160(c, d, e, a, b, x[ 5], 7) - HHH160(b, c, d, e, a, x[ 1], 15) - HHH160(a, b, c, d, e, x[ 3], 11) - HHH160(e, a, b, c, d, x[ 7], 8) - HHH160(d, e, a, b, c, x[14], 6) - HHH160(c, d, e, a, b, x[ 6], 6) - HHH160(b, c, d, e, a, x[ 9], 14) - HHH160(a, b, c, d, e, x[11], 12) - HHH160(e, a, b, c, d, x[ 8], 13) - HHH160(d, e, a, b, c, x[12], 5) - HHH160(c, d, e, a, b, x[ 2], 14) - HHH160(b, c, d, e, a, x[10], 13) - HHH160(a, b, c, d, e, x[ 0], 13) - HHH160(e, a, b, c, d, x[ 4], 7) - HHH160(d, e, a, b, c, x[13], 5) - -template RROUND160N4(a, b, c, d, e, x): void = - GGG160(c, d, e, a, b, x[ 8], 15) - GGG160(b, c, d, e, a, x[ 6], 5) - GGG160(a, b, c, d, e, x[ 4], 8) - GGG160(e, a, b, c, d, x[ 1], 11) - GGG160(d, e, a, b, c, x[ 3], 14) - GGG160(c, d, e, a, b, x[11], 14) - GGG160(b, c, d, e, a, x[15], 6) - GGG160(a, b, c, d, e, x[ 0], 14) - GGG160(e, a, b, c, d, x[ 5], 6) - GGG160(d, e, a, b, c, x[12], 9) - GGG160(c, d, e, a, b, x[ 2], 12) - GGG160(b, c, d, e, a, x[13], 9) - GGG160(a, b, c, d, e, x[ 9], 12) - GGG160(e, a, b, c, d, x[ 7], 5) - GGG160(d, e, a, b, c, x[10], 15) - GGG160(c, d, e, a, b, x[14], 8) - -template RROUND160N5(a, b, c, d, e, x): void = - FFF160(b, c, d, e, a, x[12] , 8) - FFF160(a, b, c, d, e, x[15] , 5) - FFF160(e, a, b, c, d, x[10] , 12) - FFF160(d, e, a, b, c, x[ 4] , 9) - FFF160(c, d, e, a, b, x[ 1] , 12) - FFF160(b, c, d, e, a, x[ 5] , 5) - FFF160(a, b, c, d, e, x[ 8] , 14) - FFF160(e, a, b, c, d, x[ 7] , 6) - FFF160(d, e, a, b, c, x[ 6] , 8) - FFF160(c, d, e, a, b, x[ 2] , 13) - FFF160(b, c, d, e, a, x[13] , 6) - FFF160(a, b, c, d, e, x[14] , 5) - FFF160(e, a, b, c, d, x[ 0] , 15) - FFF160(d, e, a, b, c, x[ 3] , 13) - FFF160(c, d, e, a, b, x[ 9] , 11) - FFF160(b, c, d, e, a, x[11] , 11) - -proc ripemd128Transform(state: var array[4, uint32], data: ptr byte) = - var - aa = state[0] - bb = state[1] - cc = state[2] - dd = state[3] - aaa = state[0] - bbb = state[1] - ccc = state[2] - ddd = state[3] - X = cast[ptr UncheckedArray[uint32]](data) - - LROUND128N1(aa, bb, cc, dd, X) - LROUND128N2(aa, bb, cc, dd, X) - LROUND128N3(aa, bb, cc, dd, X) - LROUND128N4(aa, bb, cc, dd, X) - RROUND128N1(aaa, bbb, ccc, ddd, X) - RROUND128N2(aaa, bbb, ccc, ddd, X) - RROUND128N3(aaa, bbb, ccc, ddd, X) - RROUND128N4(aaa, bbb, ccc, ddd, X) - - # combine results - ddd = ddd + cc + state[1] - state[1] = state[2] + dd + aaa - state[2] = state[3] + aa + bbb - state[3] = state[0] + bb + ccc - state[0] = ddd - -proc ripemd256Transform(state: var array[8, uint32], data: ptr byte) = - var - aa = state[0] - bb = state[1] - cc = state[2] - dd = state[3] - aaa = state[4] - bbb = state[5] - ccc = state[6] - ddd = state[7] - X = cast[ptr UncheckedArray[uint32]](data) - - LROUND128N1(aa, bb, cc, dd, X) - RROUND128N1(aaa, bbb, ccc, ddd, X) - swap(aa, aaa) - LROUND128N2(aa, bb, cc, dd, X) - RROUND128N2(aaa, bbb, ccc, ddd, X) - swap(bb, bbb) - LROUND128N3(aa, bb, cc, dd, X) - RROUND128N3(aaa, bbb, ccc, ddd, X) - swap(cc, ccc) - LROUND128N4(aa, bb, cc, dd, X) - RROUND128N4(aaa, bbb, ccc, ddd, X) - swap(dd, ddd) - - # combine results - state[0] = state[0] + aa - state[1] = state[1] + bb - state[2] = state[2] + cc - state[3] = state[3] + dd - state[4] = state[4] + aaa - state[5] = state[5] + bbb - state[6] = state[6] + ccc - state[7] = state[7] + ddd - -proc ripemd160Transform(state: var array[5, uint32], data: ptr byte) = - var - aa = state[0] - bb = state[1] - cc = state[2] - dd = state[3] - ee = state[4] - aaa = state[0] - bbb = state[1] - ccc = state[2] - ddd = state[3] - eee = state[4] - X = cast[ptr UncheckedArray[uint32]](data) - - LROUND160N1(aa, bb, cc, dd, ee, X) - LROUND160N2(aa, bb, cc, dd, ee, X) - LROUND160N3(aa, bb, cc, dd, ee, X) - LROUND160N4(aa, bb, cc, dd, ee, X) - LROUND160N5(aa, bb, cc, dd, ee, X) - RROUND160N1(aaa, bbb, ccc, ddd, eee, X) - RROUND160N2(aaa, bbb, ccc, ddd, eee, X) - RROUND160N3(aaa, bbb, ccc, ddd, eee, X) - RROUND160N4(aaa, bbb, ccc, ddd, eee, X) - RROUND160N5(aaa, bbb, ccc, ddd, eee, X) - - # combine results - ddd = ddd + cc + state[1] - state[1] = state[2] + dd + eee - state[2] = state[3] + ee + aaa - state[3] = state[4] + aa + bbb - state[4] = state[0] + bb + ccc - state[0] = ddd - -proc ripemd320Transform(state: var array[10, uint32], data: ptr byte) = - var - aa = state[0] - bb = state[1] - cc = state[2] - dd = state[3] - ee = state[4] - aaa = state[5] - bbb = state[6] - ccc = state[7] - ddd = state[8] - eee = state[9] - X = cast[ptr UncheckedArray[uint32]](data) - - LROUND160N1(aa, bb, cc, dd, ee, X) - RROUND160N1(aaa, bbb, ccc, ddd, eee, X) - swap(aa, aaa) - LROUND160N2(aa, bb, cc, dd, ee, X) - RROUND160N2(aaa, bbb, ccc, ddd, eee, X) - swap(bb, bbb) - LROUND160N3(aa, bb, cc, dd, ee, X) - RROUND160N3(aaa, bbb, ccc, ddd, eee, X) - swap(cc, ccc) - LROUND160N4(aa, bb, cc, dd, ee, X) - RROUND160N4(aaa, bbb, ccc, ddd, eee, X) - swap(dd, ddd) - LROUND160N5(aa, bb, cc, dd, ee, X) - RROUND160N5(aaa, bbb, ccc, ddd, eee, X) - swap(ee, eee) - - # combine results - state[0] = state[0] + aa - state[1] = state[1] + bb - state[2] = state[2] + cc - state[3] = state[3] + dd - state[4] = state[4] + ee - state[5] = state[5] + aaa - state[6] = state[6] + bbb - state[7] = state[7] + ccc - state[8] = state[8] + ddd - state[9] = state[9] + eee - -template sizeDigest*(ctx: RipemdContext): uint = - (ctx.bits div 8) - -template sizeBlock*(ctx: RipemdContext): uint = - (64) - -template sizeDigest*(r: typedesc[ripemd]): int = - when r is ripemd128: - (16) - elif r is ripemd160: - (20) - elif r is ripemd256: - (32) - elif r is ripemd320: - (40) - -template sizeBlock*(r: typedesc[ripemd]): int = - (64) - -proc init*(ctx: var RipemdContext) = - ctx.count[0] = 0 - ctx.count[1] = 0 - - zeroMem(addr ctx.buffer[0], sizeof(byte) * 64) - - when ctx.bits == 128: - ctx.state[0] = 0x67452301'u32 - ctx.state[1] = 0xEFCDAB89'u32 - ctx.state[2] = 0x98BADCFE'u32 - ctx.state[3] = 0x10325476'u32 - elif ctx.bits == 160: - ctx.state[0] = 0x67452301'u32 - ctx.state[1] = 0xEFCDAB89'u32 - ctx.state[2] = 0x98BADCFE'u32 - ctx.state[3] = 0x10325476'u32 - ctx.state[4] = 0xC3D2E1F0'u32 - elif ctx.bits == 256: - ctx.state[0] = 0x67452301'u32 - ctx.state[1] = 0xEFCDAB89'u32 - ctx.state[2] = 0x98BADCFE'u32 - ctx.state[3] = 0x10325476'u32 - ctx.state[4] = 0x76543210'u32 - ctx.state[5] = 0xFEDCBA98'u32 - ctx.state[6] = 0x89ABCDEF'u32 - ctx.state[7] = 0x01234567'u32 - elif ctx.bits == 320: - ctx.state[0] = 0x67452301'u32 - ctx.state[1] = 0xEFCDAB89'u32 - ctx.state[2] = 0x98BADCFE'u32 - ctx.state[3] = 0x10325476'u32 - ctx.state[4] = 0xC3D2E1F0'u32 - ctx.state[5] = 0x76543210'u32 - ctx.state[6] = 0xFEDCBA98'u32 - ctx.state[7] = 0x89ABCDEF'u32 - ctx.state[8] = 0x01234567'u32 - ctx.state[9] = 0x3C2D1E0F'u32 - -proc clear*(ctx: var RipemdContext) {.inline.} = - burnMem(ctx) - -proc update*(ctx: var RipemdContext, data: ptr byte, ulen: uint) = - var pos = 0'u - var length = ulen - - while length > 0'u: - let offset = cast[uint](ctx.count[0] and 0x3F) - let size = min(64'u - offset, length) - copyMem(addr(ctx.buffer[offset]), - cast[pointer](cast[uint](data) + pos), size) - pos = pos + size - length = length - size - ctx.count[0] += cast[uint32](size) - if ctx.count[0] < cast[uint32](size): - ctx.count[1] += 1'u32 - if (ctx.count[0] and 0x3F) == 0: - when ctx.bits == 128: - ripemd128Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 160: - ripemd160Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 256: - ripemd256Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 320: - ripemd320Transform(ctx.state, addr(ctx.buffer[0])) - -proc update*[T: bchar](ctx: var RipemdContext, data: openarray[T]) = - if len(data) == 0: - ctx.update(nil, 0) - else: - ctx.update(cast[ptr byte](unsafeAddr data[0]), cast[uint](len(data))) - -proc finalize(ctx: var RipemdContext) = - let size = (ctx.count[0] and 0x3F) - var buffer = addr(ctx.buffer[0]) - zeroMem(addr(ctx.buffer[size]), 0x40'u - size) - ctx.buffer[size] = 0x80 - if size > 55'u32: - when ctx.bits == 128: - ripemd128Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 160: - ripemd160Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 256: - ripemd256Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 320: - ripemd320Transform(ctx.state, addr(ctx.buffer[0])) - zeroMem(addr(ctx.buffer[0]), 0x40) - SET_DWORD(buffer, 14, (ctx.count[0]) shl 3) - SET_DWORD(buffer, 15, (ctx.count[0] shr 29) or (ctx.count[1] shl 3)) - when ctx.bits == 128: - ripemd128Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 160: - ripemd160Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 256: - ripemd256Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bits == 320: - ripemd320Transform(ctx.state, addr(ctx.buffer[0])) - -proc finish*(ctx: var RipemdContext, data: ptr byte, ulen: uint): uint = - result = 0 - finalize(ctx) - when ctx.bits == 128: - if ulen >= 16'u: - result = sizeDigest(ctx) - for i in 0..3: - SET_DWORD(data, i, BSWAP(ctx.state[i])) - elif ctx.bits == 160: - if ulen >= 20'u: - result = sizeDigest(ctx) - for i in 0..4: - SET_DWORD(data, i, BSWAP(ctx.state[i])) - elif ctx.bits == 256: - if ulen >= 32'u: - result = sizeDigest(ctx) - for i in 0..7: - SET_DWORD(data, i, BSWAP(ctx.state[i])) - elif ctx.bits == 320: - if ulen >= 40'u: - result = sizeDigest(ctx) - for i in 0..9: - SET_DWORD(data, i, BSWAP(ctx.state[i])) - -proc finish*(ctx: var RipemdContext): MDigest[ctx.bits] = - discard finish(ctx, cast[ptr byte](addr result.data[0]), - cast[uint](len(result.data))) - -proc finish*[T: bchar](ctx: var RipemdContext, data: var openarray[T]) = - assert(uint(len(data)) >= ctx.sizeDigest) - discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data))) diff --git a/src/blobsets/priv/nimcrypto/sha2.nim b/src/blobsets/priv/nimcrypto/sha2.nim deleted file mode 100644 index ec91bf0..0000000 --- a/src/blobsets/priv/nimcrypto/sha2.nim +++ /dev/null @@ -1,572 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements SHA2 (Secure Hash Algorithm 2) set of cryptographic -## hash functions designed by National Security Agency, version FIPS-180-4. -## [http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf] -## -## Tests made according to official test vectors -## [http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf]. - -import hash, utils - -{.deadCodeElim:on.} - -const - ## Compile with ``-d:smallcode`` to generate smaller code footprint - smallCode = defined(smallcode) - - K0 = [ - 0x428a2f98'u32, 0x71374491'u32, 0xb5c0fbcf'u32, 0xe9b5dba5'u32, - 0x3956c25b'u32, 0x59f111f1'u32, 0x923f82a4'u32, 0xab1c5ed5'u32, - 0xd807aa98'u32, 0x12835b01'u32, 0x243185be'u32, 0x550c7dc3'u32, - 0x72be5d74'u32, 0x80deb1fe'u32, 0x9bdc06a7'u32, 0xc19bf174'u32, - 0xe49b69c1'u32, 0xefbe4786'u32, 0x0fc19dc6'u32, 0x240ca1cc'u32, - 0x2de92c6f'u32, 0x4a7484aa'u32, 0x5cb0a9dc'u32, 0x76f988da'u32, - 0x983e5152'u32, 0xa831c66d'u32, 0xb00327c8'u32, 0xbf597fc7'u32, - 0xc6e00bf3'u32, 0xd5a79147'u32, 0x06ca6351'u32, 0x14292967'u32, - 0x27b70a85'u32, 0x2e1b2138'u32, 0x4d2c6dfc'u32, 0x53380d13'u32, - 0x650a7354'u32, 0x766a0abb'u32, 0x81c2c92e'u32, 0x92722c85'u32, - 0xa2bfe8a1'u32, 0xa81a664b'u32, 0xc24b8b70'u32, 0xc76c51a3'u32, - 0xd192e819'u32, 0xd6990624'u32, 0xf40e3585'u32, 0x106aa070'u32, - 0x19a4c116'u32, 0x1e376c08'u32, 0x2748774c'u32, 0x34b0bcb5'u32, - 0x391c0cb3'u32, 0x4ed8aa4a'u32, 0x5b9cca4f'u32, 0x682e6ff3'u32, - 0x748f82ee'u32, 0x78a5636f'u32, 0x84c87814'u32, 0x8cc70208'u32, - 0x90befffa'u32, 0xa4506ceb'u32, 0xbef9a3f7'u32, 0xc67178f2'u32 - ] - - K1 = [ - 0x428a2f98d728ae22'u64, 0x7137449123ef65cd'u64, 0xb5c0fbcfec4d3b2f'u64, - 0xe9b5dba58189dbbc'u64, 0x3956c25bf348b538'u64, 0x59f111f1b605d019'u64, - 0x923f82a4af194f9b'u64, 0xab1c5ed5da6d8118'u64, 0xd807aa98a3030242'u64, - 0x12835b0145706fbe'u64, 0x243185be4ee4b28c'u64, 0x550c7dc3d5ffb4e2'u64, - 0x72be5d74f27b896f'u64, 0x80deb1fe3b1696b1'u64, 0x9bdc06a725c71235'u64, - 0xc19bf174cf692694'u64, 0xe49b69c19ef14ad2'u64, 0xefbe4786384f25e3'u64, - 0x0fc19dc68b8cd5b5'u64, 0x240ca1cc77ac9c65'u64, 0x2de92c6f592b0275'u64, - 0x4a7484aa6ea6e483'u64, 0x5cb0a9dcbd41fbd4'u64, 0x76f988da831153b5'u64, - 0x983e5152ee66dfab'u64, 0xa831c66d2db43210'u64, 0xb00327c898fb213f'u64, - 0xbf597fc7beef0ee4'u64, 0xc6e00bf33da88fc2'u64, 0xd5a79147930aa725'u64, - 0x06ca6351e003826f'u64, 0x142929670a0e6e70'u64, 0x27b70a8546d22ffc'u64, - 0x2e1b21385c26c926'u64, 0x4d2c6dfc5ac42aed'u64, 0x53380d139d95b3df'u64, - 0x650a73548baf63de'u64, 0x766a0abb3c77b2a8'u64, 0x81c2c92e47edaee6'u64, - 0x92722c851482353b'u64, 0xa2bfe8a14cf10364'u64, 0xa81a664bbc423001'u64, - 0xc24b8b70d0f89791'u64, 0xc76c51a30654be30'u64, 0xd192e819d6ef5218'u64, - 0xd69906245565a910'u64, 0xf40e35855771202a'u64, 0x106aa07032bbd1b8'u64, - 0x19a4c116b8d2d0c8'u64, 0x1e376c085141ab53'u64, 0x2748774cdf8eeb99'u64, - 0x34b0bcb5e19b48a8'u64, 0x391c0cb3c5c95a63'u64, 0x4ed8aa4ae3418acb'u64, - 0x5b9cca4f7763e373'u64, 0x682e6ff3d6b2b8a3'u64, 0x748f82ee5defb2fc'u64, - 0x78a5636f43172f60'u64, 0x84c87814a1f0ab72'u64, 0x8cc702081a6439ec'u64, - 0x90befffa23631e28'u64, 0xa4506cebde82bde9'u64, 0xbef9a3f7b2c67915'u64, - 0xc67178f2e372532b'u64, 0xca273eceea26619c'u64, 0xd186b8c721c0c207'u64, - 0xeada7dd6cde0eb1e'u64, 0xf57d4f7fee6ed178'u64, 0x06f067aa72176fba'u64, - 0x0a637dc5a2c898a6'u64, 0x113f9804bef90dae'u64, 0x1b710b35131c471b'u64, - 0x28db77f523047d84'u64, 0x32caab7b40c72493'u64, 0x3c9ebe0a15c9bebc'u64, - 0x431d67c49c100d4c'u64, 0x4cc5d4becb3e42b6'u64, 0x597f299cfc657e2a'u64, - 0x5fcb6fab3ad6faec'u64, 0x6c44198c4a475817'u64 - ] - -template CH0(x, y, z): uint32 = - ((x) and (y)) xor (not(x) and (z)) -template MAJ0(x, y, z): uint32 = - ((x) and (y)) xor ((x) and (z)) xor ((y) and (z)) -template CH1(x, y, z): uint64 = - ((x) and (y)) xor (not(x) and (z)) -template MAJ1(x, y, z): uint64 = - ((x) and (y)) xor ((x) and (z)) xor ((y) and (z)) -template TAU0(x: uint32): uint32 = - (ROR(x, 2) xor ROR(x, 13) xor ROR(x, 22)) -template TAU1(x: uint32): uint32 = - (ROR(x, 6) xor ROR(x, 11) xor ROR(x, 25)) -template SIG0(x): uint32 = - ROR(x, 7) xor ROR(x, 18) xor (x shr 3) -template SIG1(x): uint32 = - ROR(x, 17) xor ROR(x, 19) xor (x shr 10) -template PHI0(x): uint64 = - ROR(x, 28) xor ROR(x, 34) xor ROR(x, 39) -template PHI1(x): uint64 = - ROR(x, 14) xor ROR(x, 18) xor ROR(x, 41) -template RHO0(x): uint64 = - ROR(x, 1) xor ROR(x, 8) xor (x shr 7) -template RHO1(x): uint64 = - ROR(x, 19) xor ROR(x, 61) xor (x shr 6) - -type - Sha2Context*[bits: static[int], - bsize: static[int], - T: uint32|uint64] = object - count: array[2, T] - state: array[8, T] - buffer: array[bsize, byte] - - sha224* = Sha2Context[224, 64, uint32] - sha256* = Sha2Context[256, 64, uint32] - sha384* = Sha2Context[384, 128, uint64] - sha512* = Sha2Context[512, 128, uint64] - sha512_224* = Sha2Context[224, 128, uint64] - sha512_256* = Sha2Context[256, 128, uint64] - sha2* = sha224 | sha256 | sha384 | sha512 | sha512_224 | sha512_256 - -template sizeDigest*(ctx: Sha2Context): uint = - (ctx.bits div 8) - -template sizeBlock*(ctx: Sha2Context): uint = - (ctx.bsize) - -template sizeDigest*(r: typedesc[sha2]): int = - when r is sha224 or r is sha512_224: - (28) - elif r is sha256 or r is sha512_256: - (32) - elif r is sha384: - (48) - elif r is sha512: - (64) - -template sizeBlock*(r: typedesc[sha2]): int = - when r is sha224 or r is sha256: - (64) - else: - (128) - -proc init*(ctx: var Sha2Context) = - ctx.count[0] = 0 - ctx.count[1] = 0 - when ctx.bits == 224 and ctx.bsize == 64: - ctx.state[0] = 0xC1059ED8'u32 - ctx.state[1] = 0x367CD507'u32 - ctx.state[2] = 0x3070DD17'u32 - ctx.state[3] = 0xF70E5939'u32 - ctx.state[4] = 0xFFC00B31'u32 - ctx.state[5] = 0x68581511'u32 - ctx.state[6] = 0x64F98FA7'u32 - ctx.state[7] = 0xBEFA4FA4'u32 - elif ctx.bits == 256 and ctx.bsize == 64: - ctx.state[0] = 0x6A09E667'u32 - ctx.state[1] = 0xBB67AE85'u32 - ctx.state[2] = 0x3C6EF372'u32 - ctx.state[3] = 0xA54FF53A'u32 - ctx.state[4] = 0x510E527F'u32 - ctx.state[5] = 0x9B05688C'u32 - ctx.state[6] = 0x1F83D9AB'u32 - ctx.state[7] = 0x5BE0CD19'u32 - elif ctx.bits == 384 and ctx.bsize == 128: - ctx.state[0] = 0xCBBB9D5DC1059ED8'u64 - ctx.state[1] = 0x629A292A367CD507'u64 - ctx.state[2] = 0x9159015A3070DD17'u64 - ctx.state[3] = 0x152FECD8F70E5939'u64 - ctx.state[4] = 0x67332667FFC00B31'u64 - ctx.state[5] = 0x8EB44A8768581511'u64 - ctx.state[6] = 0xDB0C2E0D64F98FA7'u64 - ctx.state[7] = 0x47B5481DBEFA4FA4'u64 - elif ctx.bits == 512 and ctx.bsize == 128: - ctx.state[0] = 0x6A09E667F3BCC908'u64 - ctx.state[1] = 0xBB67AE8584CAA73B'u64 - ctx.state[2] = 0x3C6EF372FE94F82B'u64 - ctx.state[3] = 0xA54FF53A5F1D36F1'u64 - ctx.state[4] = 0x510E527FADE682D1'u64 - ctx.state[5] = 0x9B05688C2B3E6C1F'u64 - ctx.state[6] = 0x1F83D9ABFB41BD6B'u64 - ctx.state[7] = 0x5BE0CD19137E2179'u64 - elif ctx.bits == 224 and ctx.bsize == 128: - ctx.state[0] = 0x8C3D37C819544DA2'u64 - ctx.state[1] = 0x73E1996689DCD4D6'u64 - ctx.state[2] = 0x1DFAB7AE32FF9C82'u64 - ctx.state[3] = 0x679DD514582F9FCF'u64 - ctx.state[4] = 0x0F6D2B697BD44DA8'u64 - ctx.state[5] = 0x77E36F7304C48942'u64 - ctx.state[6] = 0x3F9D85A86A1D36C8'u64 - ctx.state[7] = 0x1112E6AD91D692A1'u64 - elif ctx.bits == 256 and ctx.bsize == 128: - ctx.state[0] = 0x22312194FC2BF72C'u64 - ctx.state[1] = 0x9F555FA3C84C64C2'u64 - ctx.state[2] = 0x2393B86B6F53B151'u64 - ctx.state[3] = 0x963877195940EABD'u64 - ctx.state[4] = 0x96283EE2A88EFFE3'u64 - ctx.state[5] = 0xBE5E1E2553863992'u64 - ctx.state[6] = 0x2B0199FC2C85B8AA'u64 - ctx.state[7] = 0x0EB72DDC81C52CA2'u64 - -proc clear*(ctx: var Sha2Context) {.inline.} = - burnMem(ctx) - -when not smallCode: - template ROUND256(a, b, c, d, e, f, g, h, z) = - t0 = h + TAU1(e) + CH0(e, f, g) + K0[z] + W[z] - t1 = TAU0(a) + MAJ0(a, b, c) - d = d + t0 - h = t0 + t1 - - template ROUND512(a, b, c, d, e, f, g, h, z) = - t0 = h + PHI1(e) + CH1(e, f, g) + K1[z] + W[z] - t1 = PHI0(a) + MAJ1(a, b, c) - d = d + t0 - h = t0 + t1 - -proc sha256Transform(state: var array[8, uint32], data: ptr byte) = - var t0, t1: uint32 - var W: array[64, uint32] - - var i = 0 - while i < 16: - W[i] = LSWAP(GET_DWORD(data, i)) - inc(i) - while i < 64: - W[i] = SIG1(W[i - 2]) + W[i - 7] + SIG0(W[i - 15]) + W[i - 16] - inc(i) - - var s0 = state[0] - var s1 = state[1] - var s2 = state[2] - var s3 = state[3] - var s4 = state[4] - var s5 = state[5] - var s6 = state[6] - var s7 = state[7] - - when smallCode: - i = 0 - while i < 64: - t0 = s7 + TAU1(s4) + CH0(s4, s5, s6) + K0[i] + W[i] - t1 = TAU0(s0) + MAJ0(s0, s1, s2) - s7 = s6 - s6 = s5 - s5 = s4 - s4 = s3 + t0 - s3 = s2 - s2 = s1 - s1 = s0 - s0 = t0 + t1 - inc(i) - else: - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 0) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 1) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 2) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 3) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 4) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 5) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 6) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 7) - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 8) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 9) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 10) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 11) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 12) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 13) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 14) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 15) - - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 16) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 17) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 18) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 19) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 20) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 21) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 22) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 23) - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 24) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 25) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 26) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 27) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 28) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 29) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 30) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 31) - - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 32) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 33) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 34) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 35) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 36) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 37) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 38) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 39) - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 40) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 41) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 42) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 43) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 44) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 45) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 46) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 47) - - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 48) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 49) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 50) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 51) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 52) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 53) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 54) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 55) - ROUND256(s0, s1, s2, s3, s4, s5, s6, s7, 56) - ROUND256(s7, s0, s1, s2, s3, s4, s5, s6, 57) - ROUND256(s6, s7, s0, s1, s2, s3, s4, s5, 58) - ROUND256(s5, s6, s7, s0, s1, s2, s3, s4, 59) - ROUND256(s4, s5, s6, s7, s0, s1, s2, s3, 60) - ROUND256(s3, s4, s5, s6, s7, s0, s1, s2, 61) - ROUND256(s2, s3, s4, s5, s6, s7, s0, s1, 62) - ROUND256(s1, s2, s3, s4, s5, s6, s7, s0, 63) - - state[0] += s0 - state[1] += s1 - state[2] += s2 - state[3] += s3 - state[4] += s4 - state[5] += s5 - state[6] += s6 - state[7] += s7 - -proc sha512Transform(state: var array[8, uint64], data: ptr byte) = - var t0, t1: uint64 - var W: array[80, uint64] - - var i = 0 - while i < 16: - W[i] = LSWAP(GET_QWORD(data, i)) - inc(i) - while i < 80: - W[i] = RHO1(W[i - 2]) + W[i - 7] + RHO0(W[i - 15]) + W[i - 16] - inc(i) - - var s0 = state[0] - var s1 = state[1] - var s2 = state[2] - var s3 = state[3] - var s4 = state[4] - var s5 = state[5] - var s6 = state[6] - var s7 = state[7] - - when smallCode: - i = 0 - while i < 80: - t0 = s7 + PHI1(s4) + CH1(s4, s5, s6) + K1[i] + W[i] - t1 = PHI0(s0) + MAJ1(s0, s1, s2) - s7 = s6 - s6 = s5 - s5 = s4 - s4 = s3 + t0 - s3 = s2 - s2 = s1 - s1 = s0 - s0 = t0 + t1 - inc(i) - else: - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 0) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 1) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 2) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 3) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 4) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 5) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 6) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 7) - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 8) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 9) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 10) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 11) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 12) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 13) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 14) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 15) - - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 16) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 17) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 18) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 19) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 20) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 21) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 22) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 23) - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 24) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 25) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 26) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 27) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 28) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 29) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 30) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 31) - - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 32) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 33) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 34) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 35) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 36) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 37) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 38) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 39) - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 40) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 41) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 42) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 43) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 44) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 45) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 46) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 47) - - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 48) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 49) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 50) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 51) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 52) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 53) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 54) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 55) - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 56) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 57) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 58) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 59) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 60) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 61) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 62) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 63) - - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 64) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 65) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 66) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 67) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 68) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 69) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 70) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 71) - ROUND512(s0, s1, s2, s3, s4, s5, s6, s7, 72) - ROUND512(s7, s0, s1, s2, s3, s4, s5, s6, 73) - ROUND512(s6, s7, s0, s1, s2, s3, s4, s5, 74) - ROUND512(s5, s6, s7, s0, s1, s2, s3, s4, 75) - ROUND512(s4, s5, s6, s7, s0, s1, s2, s3, 76) - ROUND512(s3, s4, s5, s6, s7, s0, s1, s2, 77) - ROUND512(s2, s3, s4, s5, s6, s7, s0, s1, 78) - ROUND512(s1, s2, s3, s4, s5, s6, s7, s0, 79) - - state[0] += s0 - state[1] += s1 - state[2] += s2 - state[3] += s3 - state[4] += s4 - state[5] += s5 - state[6] += s6 - state[7] += s7 - -proc update*(ctx: var Sha2Context, data: ptr byte, inlen: uint) = - var pos = 0'u - var length = inlen - - when ctx.bsize == 64: - while length > 0'u: - let offset = cast[uint](ctx.count[0] and 0x3F) - let size = min(64'u - offset, length) - copyMem(addr(ctx.buffer[offset]), - cast[pointer](cast[uint](data) + pos), size) - pos = pos + size - length = length - size - ctx.count[0] += cast[uint32](size) - if ctx.count[0] < cast[uint32](size): - ctx.count[1] += 1'u32 - if (ctx.count[0] and 0x3F) == 0: - sha256Transform(ctx.state, addr(ctx.buffer[0])) - elif ctx.bsize == 128: - while length > 0'u: - let offset = cast[uint](ctx.count[0] and 0x7F) - let size = min(128'u - offset, length) - copyMem(addr(ctx.buffer[offset]), - cast[pointer](cast[uint](data) + pos), size) - pos = pos + size - length = length - size - ctx.count[0] += cast[uint64](size) - if ctx.count[0] < cast[uint64](size): - ctx.count[1] += 1'u64 - if (ctx.count[0] and 0x7F) == 0: - sha512Transform(ctx.state, addr(ctx.buffer[0])) - -proc update*[T: bchar](ctx: var Sha2Context, data: openarray[T]) = - if len(data) == 0: - ctx.update(nil, 0) - else: - ctx.update(cast[ptr byte](unsafeAddr data[0]), cast[uint](len(data))) - -proc finalize256(ctx: var Sha2Context) = - var buffer = addr(ctx.buffer[0]) - var j = int(ctx.count[0] and 0x3F) - ctx.buffer[j] = 0x80 - inc(j) - while j != 56: - if j == 64: - sha256Transform(ctx.state, buffer) - j = 0 - ctx.buffer[j] = 0x00 - inc(j) - ctx.count[1] = (ctx.count[1] shl 3) + (ctx.count[0] shr 29) - ctx.count[0] = ctx.count[0] shl 3 - SET_DWORD(buffer, 14, LSWAP(ctx.count[1])) - SET_DWORD(buffer, 15, LSWAP(ctx.count[0])) - sha256Transform(ctx.state, buffer) - -proc finalize512(ctx: var Sha2Context) = - var buffer = addr(ctx.buffer[0]) - var j = int(ctx.count[0] and 0x7F) - ctx.buffer[j] = 0x80 - inc(j) - while j != 112: - if j == 128: - sha512Transform(ctx.state, buffer) - j = 0 - ctx.buffer[j] = 0x00 - inc(j) - ctx.count[1] = (ctx.count[1] shl 3) + (ctx.count[0] shr 29) - ctx.count[0] = ctx.count[0] shl 3 - SET_QWORD(buffer, 14, LSWAP(ctx.count[1])) - SET_QWORD(buffer, 15, LSWAP(ctx.count[0])) - sha512Transform(ctx.state, buffer) - -proc finish*(ctx: var Sha2Context, pBytes: ptr byte, nBytes: uint): uint = - result = 0 - when ctx.bits == 224 and ctx.bsize == 64: - finalize256(ctx) - if nBytes >= 28'u: - result = sizeDigest(ctx) - for i in 0..6: - SET_DWORD(pBytes, i, LSWAP(ctx.state[i])) - elif ctx.bits == 256 and ctx.bsize == 64: - finalize256(ctx) - if nBytes >= 32'u: - result = sizeDigest(ctx) - for i in 0..7: - SET_DWORD(pBytes, i, LSWAP(ctx.state[i])) - elif ctx.bits == 384 and ctx.bsize == 128: - finalize512(ctx) - if nBytes >= 48'u: - result = sizeDigest(ctx) - for i in 0..5: - SET_QWORD(pBytes, i, LSWAP(ctx.state[i])) - elif ctx.bits == 512 and ctx.bsize == 128: - finalize512(ctx) - if nBytes >= 64'u: - result = sizeDigest(ctx) - for i in 0..7: - SET_QWORD(pBytes, i, LSWAP(ctx.state[i])) - elif ctx.bits == 256 and ctx.bsize == 128: - finalize512(ctx) - if nBytes >= 32'u: - result = sizeDigest(ctx) - for i in 0..3: - SET_QWORD(pBytes, i, LSWAP(ctx.state[i])) - elif ctx.bits == 224 and ctx.bsize == 128: - finalize512(ctx) - if nBytes >= 28'u: - result = sizeDigest(ctx) - SET_QWORD(pBytes, 0, LSWAP(ctx.state[0])) - SET_QWORD(pBytes, 1, LSWAP(ctx.state[1])) - SET_QWORD(pBytes, 2, LSWAP(ctx.state[2])) - SET_DWORD(pBytes, 6, cast[uint32](LSWAP(ctx.state[3]))) - -proc finish*(ctx: var Sha2Context): MDigest[ctx.bits] = - discard finish(ctx, cast[ptr byte](addr result.data[0]), - cast[uint](len(result.data))) - -proc finish*[T: bchar](ctx: var Sha2Context, data: var openarray[T]) = - assert(cast[uint](len(data)) >= ctx.sizeDigest) - discard ctx.finish(cast[ptr byte](addr data[0]), cast[uint](len(data))) diff --git a/src/blobsets/priv/nimcrypto/sysrand.nim b/src/blobsets/priv/nimcrypto/sysrand.nim deleted file mode 100644 index 9925e5c..0000000 --- a/src/blobsets/priv/nimcrypto/sysrand.nim +++ /dev/null @@ -1,289 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2018 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements interface to operation system's random number -## generator. -## -## ``Windows`` using BCryptGenRandom (if available), -## CryptGenRandom(PROV_INTEL_SEC) (if available), RtlGenRandom. -## -## RtlGenRandom (available from Windows XP) -## BCryptGenRandom (available from Windows Vista SP1) -## CryptGenRandom(PROV_INTEL_SEC) (only when Intel SandyBridge -## CPU is available). -## -## ``Linux`` using genrandom (if available), `/dev/urandom`. -## -## ``OpenBSD`` using getentropy. -## -## ``NetBSD``, ``FreeBSD``, ``MacOS``, ``Solaris`` using `/dev/urandom`. - -{.deadCodeElim:on.} - -when defined(posix): - import os, posix - - proc urandomRead(pbytes: pointer, nbytes: int): int = - result = -1 - var st: Stat - let fd = posix.open("/dev/urandom", posix.O_RDONLY) - if fd != -1: - if posix.fstat(fd, st) != -1 and S_ISCHR(st.st_mode): - result = 0 - while result < nbytes: - var p = cast[pointer](cast[uint]((pbytes)) + uint(result)) - var res = posix.read(fd, p, nbytes - result) - if res > 0: - result += res - elif res == 0: - break - else: - if osLastError().int32 != EINTR: - result = -1 - break - discard posix.close(fd) - -when defined(openbsd): - import posix, os - - proc getentropy(pBytes: pointer, nBytes: int): cint - {.importc: "getentropy", header: "".} - - proc randomBytes*(pbytes: pointer, nbytes: int): int = - var p: pointer - while result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = getentropy(p, nbytes - result) - if res > 0: - result += res - elif res == 0: - break - else: - if osLastError().int32 != EINTR: - result = -1 - break - - if result == -1: - result = urandomRead(pbytes, nbytes) - elif result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = urandomRead(p, nbytes - result) - if res != -1: - result += res - -elif defined(linux): - import posix, os - when defined(i386): - const SYS_getrandom = 355 - elif defined(powerpc64) or defined(powerpc64el) or defined(powerpc): - const SYS_getrandom = 359 - elif defined(arm64): - const SYS_getrandom = 278 - elif defined(arm): - const SYS_getrandom = 384 - elif defined(amd64): - const SYS_getrandom = 318 - elif defined(mips): - when sizeof(int) == 8: - const SYS_getrandom = 4000 + 313 - else: - const SYS_getrandom = 4000 + 353 - else: - const SYS_getrandom = 0 - const - GRND_NONBLOCK = 1 - - type - SystemRng = ref object of RootRef - getRandomPresent: bool - - proc syscall(number: clong): clong {.importc: "syscall", - header: """#include - #include """, varargs, discardable.} - - var gSystemRng {.threadvar.}: SystemRng ## System thread global RNG - - proc newSystemRNG(): SystemRng = - result = SystemRng() - - if SYS_getrandom != 0: - var data: int - result.getRandomPresent = true - let res = syscall(SYS_getrandom, addr data, 1, GRND_NONBLOCK) - if res == -1: - let err = osLastError().int32 - if err == ENOSYS or err == EPERM: - result.getRandomPresent = false - - proc getSystemRNG(): SystemRng = - if gSystemRng.isNil: gSystemRng = newSystemRng() - result = gSystemRng - - proc randomBytes*(pbytes: pointer, nbytes: int): int = - var p: pointer - let srng = getSystemRNG() - if srng.getRandomPresent: - while result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = syscall(SYS_getrandom, pBytes, nBytes - result, 0) - if res > 0: - result += res - elif res == 0: - break - else: - if osLastError().int32 != EINTR: - result = -1 - break - - if result == -1: - result = urandomRead(pbytes, nbytes) - elif result < nbytes: - p = cast[pointer](cast[uint](pbytes) + uint(result)) - let res = urandomRead(p, nbytes - result) - if res != -1: - result += res - else: - result = urandomRead(pbytes, nbytes) - -elif defined(windows): - import os, winlean, dynlib - - const - VER_GREATER_EQUAL = 3'u8 - VER_MINORVERSION = 0x0000001 - VER_MAJORVERSION = 0x0000002 - VER_SERVICEPACKMINOR = 0x0000010 - VER_SERVICEPACKMAJOR = 0x0000020 - PROV_INTEL_SEC = 22 - INTEL_DEF_PROV = "Intel Hardware Cryptographic Service Provider" - CRYPT_VERIFYCONTEXT = 0xF0000000'i32 - CRYPT_SILENT = 0x00000040'i32 - BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002 - type - OSVERSIONINFOEXW {.final, pure.} = object - dwOSVersionInfoSize: DWORD - dwMajorVersion: DWORD - dwMinorVersion: DWORD - dwBuildNumber: DWORD - dwPlatformId: DWORD - szCSDVersion: array[128, Utf16Char] - wServicePackMajor: uint16 - wServicePackMinor: uint16 - wSuiteMask: uint16 - wProductType: byte - wReserved: byte - - HCRYPTPROV = uint - - BCGRMPROC = proc(hAlgorithm: pointer, pBuffer: pointer, cBuffer: ULONG, - dwFlags: ULONG): LONG {.stdcall, gcsafe.} - QPCPROC = proc(hProcess: Handle, cycleTime: var uint64): WINBOOL {. - stdcall, gcsafe.} - QUITPROC = proc(itime: var uint64) {.stdcall, gcsafe.} - QIPCPROC = proc(bufferLength: var uint32, idleTime: ptr uint64): WINBOOL {. - stdcall, gcsafe.} - - SystemRng = ref object of RootRef - bCryptGenRandom: BCGRMPROC - queryProcessCycleTime: QPCPROC - queryUnbiasedInterruptTime: QUITPROC - queryIdleProcessorCycleTime: QIPCPROC - coresCount: uint32 - hIntel: HCRYPTPROV - - var gSystemRng {.threadvar.}: SystemRng ## System thread global RNG - - proc verifyVersionInfo(lpVerInfo: ptr OSVERSIONINFOEXW, dwTypeMask: DWORD, - dwlConditionMask: uint64): WINBOOL - {.importc: "VerifyVersionInfoW", stdcall, dynlib: "kernel32.dll".} - proc verSetConditionMask(conditionMask: uint64, dwTypeMask: DWORD, - condition: byte): uint64 - {.importc: "VerSetConditionMask", stdcall, dynlib: "kernel32.dll".} - proc cryptAcquireContext(phProv: ptr HCRYPTPROV, pszContainer: WideCString, - pszProvider: WideCString, dwProvType: DWORD, - dwFlags: DWORD): WINBOOL - {.importc: "CryptAcquireContextW", stdcall, dynlib: "advapi32.dll".} - proc cryptReleaseContext(phProv: HCRYPTPROV, dwFlags: DWORD): WINBOOL - {.importc: "CryptReleaseContext", stdcall, dynlib: "advapi32.dll".} - proc cryptGenRandom(phProv: HCRYPTPROV, dwLen: DWORD, - pBuffer: pointer): WINBOOL - {.importc: "CryptGenRandom", stdcall, dynlib: "advapi32.dll".} - proc rtlGenRandom(bufptr: pointer, buflen: ULONG): WINBOOL - {.importc: "SystemFunction036", stdcall, dynlib: "advapi32.dll".} - - proc isEqualOrHigher(major: int, minor: int, servicePack: int): bool = - var mask = 0'u64 - var ov = OSVERSIONINFOEXW() - ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW).DWORD - ov.dwMajorVersion = major.DWORD - ov.dwMinorVersion = minor.DWORD - ov.wServicePackMajor = servicePack.uint16 - ov.wServicePackMinor = 0 - var typeMask = (VER_MAJORVERSION or VER_MINORVERSION or - VER_SERVICEPACKMAJOR or VER_SERVICEPACKMINOR).DWORD - mask = verSetConditionMask(mask, VER_MAJORVERSION, VER_GREATER_EQUAL) - mask = verSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL) - mask = verSetConditionMask(mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL) - mask = verSetConditionMask(mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL) - return (verifyVersionInfo(addr ov, typeMask, mask) == 1) - - proc newSystemRNG(): SystemRng = - result = SystemRng() - if isEqualOrHigher(6, 0, 0): - if isEqualOrHigher(6, 0, 1): - let lib = loadLib("bcrypt.dll") - if lib != nil: - var lProc = cast[BCGRMPROC](symAddr(lib, "BCryptGenRandom")) - if not isNil(lProc): - result.bCryptGenRandom = lProc - - var hp: HCRYPTPROV = 0 - let intelDef = newWideCString(INTEL_DEF_PROV) - let res1 = cryptAcquireContext(addr hp, nil, intelDef, PROV_INTEL_SEC, - CRYPT_VERIFYCONTEXT or CRYPT_SILENT).bool - if res1: - result.hIntel = hp - - proc getSystemRNG(): SystemRng = - if gSystemRng.isNil: gSystemRng = newSystemRng() - result = gSystemRng - - proc randomBytes*(pbytes: pointer, nbytes: int): int = - let srng = getSystemRNG() - result = -1 - if not isNil(srng.bCryptGenRandom): - if srng.bCryptGenRandom(nil, pbytes, nbytes.ULONG, - BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0: - result = nbytes - - if srng.hIntel != 0 and result == -1: - if cryptGenRandom(srng.hIntel, nbytes.DWORD, pbytes) != 0: - result = nbytes - - if result == -1: - if rtlGenRandom(pBytes, nbytes.ULONG) != 0: - result = nbytes - - proc randomClose*() = - let srng = getSystemRNG() - if srng.hIntel != 0: - if cryptReleaseContext(srng.hIntel, 0) == 0: - raiseOsError(osLastError()) -else: - import posix, os - - proc randomBytes*(pbytes: pointer, nbytes: int): int = - result = urandomRead(pbytes, nbytes) - -proc randomBytes*[T](bytes: var openarray[T]): int = - assert(len(bytes) > 0) - let length = len(bytes) * sizeof(T) - result = randomBytes(addr bytes[0], length) - if result != -1: - result = result div sizeof(T) diff --git a/src/blobsets/priv/nimcrypto/twofish.nim b/src/blobsets/priv/nimcrypto/twofish.nim deleted file mode 100644 index 858a997..0000000 --- a/src/blobsets/priv/nimcrypto/twofish.nim +++ /dev/null @@ -1,449 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module implements Twofish crypto algorithm by Bruce Schneier. -## -## Code based on `Optimized C` created by Drew Csillag -## [https://www.schneier.com/code/twofish-cpy.zip]. -## -## Tests made according to official test vectors -## [https://www.schneier.com/code/ecb_ival.txt]. - -import utils - -{.deadCodeElim:on.} - -const - RS_MOD = 0x14D - RHO = 0x01010101 - - RS = [ - [0x01'u8, 0xA4'u8, 0x55'u8, 0x87'u8, 0x5A'u8, 0x58'u8, 0xDB'u8, 0x9E'u8], - [0xA4'u8, 0x56'u8, 0x82'u8, 0xF3'u8, 0x1E'u8, 0xC6'u8, 0x68'u8, 0xE5'u8], - [0x02'u8, 0xA1'u8, 0xFC'u8, 0xC1'u8, 0x47'u8, 0xAE'u8, 0x3D'u8, 0x19'u8], - [0xA4'u8, 0x55'u8, 0x87'u8, 0x5A'u8, 0x58'u8, 0xDB'u8, 0x9E'u8, 0x03'u8] - ] - - Q0 = [ - 0xA9'u8, 0x67'u8, 0xB3'u8, 0xE8'u8, 0x04'u8, 0xFD'u8, 0xA3'u8, 0x76'u8, - 0x9A'u8, 0x92'u8, 0x80'u8, 0x78'u8, 0xE4'u8, 0xDD'u8, 0xD1'u8, 0x38'u8, - 0x0D'u8, 0xC6'u8, 0x35'u8, 0x98'u8, 0x18'u8, 0xF7'u8, 0xEC'u8, 0x6C'u8, - 0x43'u8, 0x75'u8, 0x37'u8, 0x26'u8, 0xFA'u8, 0x13'u8, 0x94'u8, 0x48'u8, - 0xF2'u8, 0xD0'u8, 0x8B'u8, 0x30'u8, 0x84'u8, 0x54'u8, 0xDF'u8, 0x23'u8, - 0x19'u8, 0x5B'u8, 0x3D'u8, 0x59'u8, 0xF3'u8, 0xAE'u8, 0xA2'u8, 0x82'u8, - 0x63'u8, 0x01'u8, 0x83'u8, 0x2E'u8, 0xD9'u8, 0x51'u8, 0x9B'u8, 0x7C'u8, - 0xA6'u8, 0xEB'u8, 0xA5'u8, 0xBE'u8, 0x16'u8, 0x0C'u8, 0xE3'u8, 0x61'u8, - 0xC0'u8, 0x8C'u8, 0x3A'u8, 0xF5'u8, 0x73'u8, 0x2C'u8, 0x25'u8, 0x0B'u8, - 0xBB'u8, 0x4E'u8, 0x89'u8, 0x6B'u8, 0x53'u8, 0x6A'u8, 0xB4'u8, 0xF1'u8, - 0xE1'u8, 0xE6'u8, 0xBD'u8, 0x45'u8, 0xE2'u8, 0xF4'u8, 0xB6'u8, 0x66'u8, - 0xCC'u8, 0x95'u8, 0x03'u8, 0x56'u8, 0xD4'u8, 0x1C'u8, 0x1E'u8, 0xD7'u8, - 0xFB'u8, 0xC3'u8, 0x8E'u8, 0xB5'u8, 0xE9'u8, 0xCF'u8, 0xBF'u8, 0xBA'u8, - 0xEA'u8, 0x77'u8, 0x39'u8, 0xAF'u8, 0x33'u8, 0xC9'u8, 0x62'u8, 0x71'u8, - 0x81'u8, 0x79'u8, 0x09'u8, 0xAD'u8, 0x24'u8, 0xCD'u8, 0xF9'u8, 0xD8'u8, - 0xE5'u8, 0xC5'u8, 0xB9'u8, 0x4D'u8, 0x44'u8, 0x08'u8, 0x86'u8, 0xE7'u8, - 0xA1'u8, 0x1D'u8, 0xAA'u8, 0xED'u8, 0x06'u8, 0x70'u8, 0xB2'u8, 0xD2'u8, - 0x41'u8, 0x7B'u8, 0xA0'u8, 0x11'u8, 0x31'u8, 0xC2'u8, 0x27'u8, 0x90'u8, - 0x20'u8, 0xF6'u8, 0x60'u8, 0xFF'u8, 0x96'u8, 0x5C'u8, 0xB1'u8, 0xAB'u8, - 0x9E'u8, 0x9C'u8, 0x52'u8, 0x1B'u8, 0x5F'u8, 0x93'u8, 0x0A'u8, 0xEF'u8, - 0x91'u8, 0x85'u8, 0x49'u8, 0xEE'u8, 0x2D'u8, 0x4F'u8, 0x8F'u8, 0x3B'u8, - 0x47'u8, 0x87'u8, 0x6D'u8, 0x46'u8, 0xD6'u8, 0x3E'u8, 0x69'u8, 0x64'u8, - 0x2A'u8, 0xCE'u8, 0xCB'u8, 0x2F'u8, 0xFC'u8, 0x97'u8, 0x05'u8, 0x7A'u8, - 0xAC'u8, 0x7F'u8, 0xD5'u8, 0x1A'u8, 0x4B'u8, 0x0E'u8, 0xA7'u8, 0x5A'u8, - 0x28'u8, 0x14'u8, 0x3F'u8, 0x29'u8, 0x88'u8, 0x3C'u8, 0x4C'u8, 0x02'u8, - 0xB8'u8, 0xDA'u8, 0xB0'u8, 0x17'u8, 0x55'u8, 0x1F'u8, 0x8A'u8, 0x7D'u8, - 0x57'u8, 0xC7'u8, 0x8D'u8, 0x74'u8, 0xB7'u8, 0xC4'u8, 0x9F'u8, 0x72'u8, - 0x7E'u8, 0x15'u8, 0x22'u8, 0x12'u8, 0x58'u8, 0x07'u8, 0x99'u8, 0x34'u8, - 0x6E'u8, 0x50'u8, 0xDE'u8, 0x68'u8, 0x65'u8, 0xBC'u8, 0xDB'u8, 0xF8'u8, - 0xC8'u8, 0xA8'u8, 0x2B'u8, 0x40'u8, 0xDC'u8, 0xFE'u8, 0x32'u8, 0xA4'u8, - 0xCA'u8, 0x10'u8, 0x21'u8, 0xF0'u8, 0xD3'u8, 0x5D'u8, 0x0F'u8, 0x00'u8, - 0x6F'u8, 0x9D'u8, 0x36'u8, 0x42'u8, 0x4A'u8, 0x5E'u8, 0xC1'u8, 0xE0'u8 - ] - - Q1 = [ - 0x75'u8, 0xF3'u8, 0xC6'u8, 0xF4'u8, 0xDB'u8, 0x7B'u8, 0xFB'u8, 0xC8'u8, - 0x4A'u8, 0xD3'u8, 0xE6'u8, 0x6B'u8, 0x45'u8, 0x7D'u8, 0xE8'u8, 0x4B'u8, - 0xD6'u8, 0x32'u8, 0xD8'u8, 0xFD'u8, 0x37'u8, 0x71'u8, 0xF1'u8, 0xE1'u8, - 0x30'u8, 0x0F'u8, 0xF8'u8, 0x1B'u8, 0x87'u8, 0xFA'u8, 0x06'u8, 0x3F'u8, - 0x5E'u8, 0xBA'u8, 0xAE'u8, 0x5B'u8, 0x8A'u8, 0x00'u8, 0xBC'u8, 0x9D'u8, - 0x6D'u8, 0xC1'u8, 0xB1'u8, 0x0E'u8, 0x80'u8, 0x5D'u8, 0xD2'u8, 0xD5'u8, - 0xA0'u8, 0x84'u8, 0x07'u8, 0x14'u8, 0xB5'u8, 0x90'u8, 0x2C'u8, 0xA3'u8, - 0xB2'u8, 0x73'u8, 0x4C'u8, 0x54'u8, 0x92'u8, 0x74'u8, 0x36'u8, 0x51'u8, - 0x38'u8, 0xB0'u8, 0xBD'u8, 0x5A'u8, 0xFC'u8, 0x60'u8, 0x62'u8, 0x96'u8, - 0x6C'u8, 0x42'u8, 0xF7'u8, 0x10'u8, 0x7C'u8, 0x28'u8, 0x27'u8, 0x8C'u8, - 0x13'u8, 0x95'u8, 0x9C'u8, 0xC7'u8, 0x24'u8, 0x46'u8, 0x3B'u8, 0x70'u8, - 0xCA'u8, 0xE3'u8, 0x85'u8, 0xCB'u8, 0x11'u8, 0xD0'u8, 0x93'u8, 0xB8'u8, - 0xA6'u8, 0x83'u8, 0x20'u8, 0xFF'u8, 0x9F'u8, 0x77'u8, 0xC3'u8, 0xCC'u8, - 0x03'u8, 0x6F'u8, 0x08'u8, 0xBF'u8, 0x40'u8, 0xE7'u8, 0x2B'u8, 0xE2'u8, - 0x79'u8, 0x0C'u8, 0xAA'u8, 0x82'u8, 0x41'u8, 0x3A'u8, 0xEA'u8, 0xB9'u8, - 0xE4'u8, 0x9A'u8, 0xA4'u8, 0x97'u8, 0x7E'u8, 0xDA'u8, 0x7A'u8, 0x17'u8, - 0x66'u8, 0x94'u8, 0xA1'u8, 0x1D'u8, 0x3D'u8, 0xF0'u8, 0xDE'u8, 0xB3'u8, - 0x0B'u8, 0x72'u8, 0xA7'u8, 0x1C'u8, 0xEF'u8, 0xD1'u8, 0x53'u8, 0x3E'u8, - 0x8F'u8, 0x33'u8, 0x26'u8, 0x5F'u8, 0xEC'u8, 0x76'u8, 0x2A'u8, 0x49'u8, - 0x81'u8, 0x88'u8, 0xEE'u8, 0x21'u8, 0xC4'u8, 0x1A'u8, 0xEB'u8, 0xD9'u8, - 0xC5'u8, 0x39'u8, 0x99'u8, 0xCD'u8, 0xAD'u8, 0x31'u8, 0x8B'u8, 0x01'u8, - 0x18'u8, 0x23'u8, 0xDD'u8, 0x1F'u8, 0x4E'u8, 0x2D'u8, 0xF9'u8, 0x48'u8, - 0x4F'u8, 0xF2'u8, 0x65'u8, 0x8E'u8, 0x78'u8, 0x5C'u8, 0x58'u8, 0x19'u8, - 0x8D'u8, 0xE5'u8, 0x98'u8, 0x57'u8, 0x67'u8, 0x7F'u8, 0x05'u8, 0x64'u8, - 0xAF'u8, 0x63'u8, 0xB6'u8, 0xFE'u8, 0xF5'u8, 0xB7'u8, 0x3C'u8, 0xA5'u8, - 0xCE'u8, 0xE9'u8, 0x68'u8, 0x44'u8, 0xE0'u8, 0x4D'u8, 0x43'u8, 0x69'u8, - 0x29'u8, 0x2E'u8, 0xAC'u8, 0x15'u8, 0x59'u8, 0xA8'u8, 0x0A'u8, 0x9E'u8, - 0x6E'u8, 0x47'u8, 0xDF'u8, 0x34'u8, 0x35'u8, 0x6A'u8, 0xCF'u8, 0xDC'u8, - 0x22'u8, 0xC9'u8, 0xC0'u8, 0x9B'u8, 0x89'u8, 0xD4'u8, 0xED'u8, 0xAB'u8, - 0x12'u8, 0xA2'u8, 0x0D'u8, 0x52'u8, 0xBB'u8, 0x02'u8, 0x2F'u8, 0xA9'u8, - 0xD7'u8, 0x61'u8, 0x1E'u8, 0xB4'u8, 0x50'u8, 0x04'u8, 0xF6'u8, 0xC2'u8, - 0x16'u8, 0x25'u8, 0x86'u8, 0x56'u8, 0x55'u8, 0x09'u8, 0xBE'u8, 0x91'u8 - ] - - mult5B = [ - 0x00'u8, 0x5B'u8, 0xB6'u8, 0xED'u8, 0x05'u8, 0x5E'u8, 0xB3'u8, 0xE8'u8, - 0x0A'u8, 0x51'u8, 0xBC'u8, 0xE7'u8, 0x0F'u8, 0x54'u8, 0xB9'u8, 0xE2'u8, - 0x14'u8, 0x4F'u8, 0xA2'u8, 0xF9'u8, 0x11'u8, 0x4A'u8, 0xA7'u8, 0xFC'u8, - 0x1E'u8, 0x45'u8, 0xA8'u8, 0xF3'u8, 0x1B'u8, 0x40'u8, 0xAD'u8, 0xF6'u8, - 0x28'u8, 0x73'u8, 0x9E'u8, 0xC5'u8, 0x2D'u8, 0x76'u8, 0x9B'u8, 0xC0'u8, - 0x22'u8, 0x79'u8, 0x94'u8, 0xCF'u8, 0x27'u8, 0x7C'u8, 0x91'u8, 0xCA'u8, - 0x3C'u8, 0x67'u8, 0x8A'u8, 0xD1'u8, 0x39'u8, 0x62'u8, 0x8F'u8, 0xD4'u8, - 0x36'u8, 0x6D'u8, 0x80'u8, 0xDB'u8, 0x33'u8, 0x68'u8, 0x85'u8, 0xDE'u8, - 0x50'u8, 0x0B'u8, 0xE6'u8, 0xBD'u8, 0x55'u8, 0x0E'u8, 0xE3'u8, 0xB8'u8, - 0x5A'u8, 0x01'u8, 0xEC'u8, 0xB7'u8, 0x5F'u8, 0x04'u8, 0xE9'u8, 0xB2'u8, - 0x44'u8, 0x1F'u8, 0xF2'u8, 0xA9'u8, 0x41'u8, 0x1A'u8, 0xF7'u8, 0xAC'u8, - 0x4E'u8, 0x15'u8, 0xF8'u8, 0xA3'u8, 0x4B'u8, 0x10'u8, 0xFD'u8, 0xA6'u8, - 0x78'u8, 0x23'u8, 0xCE'u8, 0x95'u8, 0x7D'u8, 0x26'u8, 0xCB'u8, 0x90'u8, - 0x72'u8, 0x29'u8, 0xC4'u8, 0x9F'u8, 0x77'u8, 0x2C'u8, 0xC1'u8, 0x9A'u8, - 0x6C'u8, 0x37'u8, 0xDA'u8, 0x81'u8, 0x69'u8, 0x32'u8, 0xDF'u8, 0x84'u8, - 0x66'u8, 0x3D'u8, 0xD0'u8, 0x8B'u8, 0x63'u8, 0x38'u8, 0xD5'u8, 0x8E'u8, - 0xA0'u8, 0xFB'u8, 0x16'u8, 0x4D'u8, 0xA5'u8, 0xFE'u8, 0x13'u8, 0x48'u8, - 0xAA'u8, 0xF1'u8, 0x1C'u8, 0x47'u8, 0xAF'u8, 0xF4'u8, 0x19'u8, 0x42'u8, - 0xB4'u8, 0xEF'u8, 0x02'u8, 0x59'u8, 0xB1'u8, 0xEA'u8, 0x07'u8, 0x5C'u8, - 0xBE'u8, 0xE5'u8, 0x08'u8, 0x53'u8, 0xBB'u8, 0xE0'u8, 0x0D'u8, 0x56'u8, - 0x88'u8, 0xD3'u8, 0x3E'u8, 0x65'u8, 0x8D'u8, 0xD6'u8, 0x3B'u8, 0x60'u8, - 0x82'u8, 0xD9'u8, 0x34'u8, 0x6F'u8, 0x87'u8, 0xDC'u8, 0x31'u8, 0x6A'u8, - 0x9C'u8, 0xC7'u8, 0x2A'u8, 0x71'u8, 0x99'u8, 0xC2'u8, 0x2F'u8, 0x74'u8, - 0x96'u8, 0xCD'u8, 0x20'u8, 0x7B'u8, 0x93'u8, 0xC8'u8, 0x25'u8, 0x7E'u8, - 0xF0'u8, 0xAB'u8, 0x46'u8, 0x1D'u8, 0xF5'u8, 0xAE'u8, 0x43'u8, 0x18'u8, - 0xFA'u8, 0xA1'u8, 0x4C'u8, 0x17'u8, 0xFF'u8, 0xA4'u8, 0x49'u8, 0x12'u8, - 0xE4'u8, 0xBF'u8, 0x52'u8, 0x09'u8, 0xE1'u8, 0xBA'u8, 0x57'u8, 0x0C'u8, - 0xEE'u8, 0xB5'u8, 0x58'u8, 0x03'u8, 0xEB'u8, 0xB0'u8, 0x5D'u8, 0x06'u8, - 0xD8'u8, 0x83'u8, 0x6E'u8, 0x35'u8, 0xDD'u8, 0x86'u8, 0x6B'u8, 0x30'u8, - 0xD2'u8, 0x89'u8, 0x64'u8, 0x3F'u8, 0xD7'u8, 0x8C'u8, 0x61'u8, 0x3A'u8, - 0xCC'u8, 0x97'u8, 0x7A'u8, 0x21'u8, 0xC9'u8, 0x92'u8, 0x7F'u8, 0x24'u8, - 0xC6'u8, 0x9D'u8, 0x70'u8, 0x2B'u8, 0xC3'u8, 0x98'u8, 0x75'u8, 0x2E'u8 - ] - - multEF = [ - 0x00'u8, 0xEF'u8, 0xB7'u8, 0x58'u8, 0x07'u8, 0xE8'u8, 0xB0'u8, 0x5F'u8, - 0x0E'u8, 0xE1'u8, 0xB9'u8, 0x56'u8, 0x09'u8, 0xE6'u8, 0xBE'u8, 0x51'u8, - 0x1C'u8, 0xF3'u8, 0xAB'u8, 0x44'u8, 0x1B'u8, 0xF4'u8, 0xAC'u8, 0x43'u8, - 0x12'u8, 0xFD'u8, 0xA5'u8, 0x4A'u8, 0x15'u8, 0xFA'u8, 0xA2'u8, 0x4D'u8, - 0x38'u8, 0xD7'u8, 0x8F'u8, 0x60'u8, 0x3F'u8, 0xD0'u8, 0x88'u8, 0x67'u8, - 0x36'u8, 0xD9'u8, 0x81'u8, 0x6E'u8, 0x31'u8, 0xDE'u8, 0x86'u8, 0x69'u8, - 0x24'u8, 0xCB'u8, 0x93'u8, 0x7C'u8, 0x23'u8, 0xCC'u8, 0x94'u8, 0x7B'u8, - 0x2A'u8, 0xC5'u8, 0x9D'u8, 0x72'u8, 0x2D'u8, 0xC2'u8, 0x9A'u8, 0x75'u8, - 0x70'u8, 0x9F'u8, 0xC7'u8, 0x28'u8, 0x77'u8, 0x98'u8, 0xC0'u8, 0x2F'u8, - 0x7E'u8, 0x91'u8, 0xC9'u8, 0x26'u8, 0x79'u8, 0x96'u8, 0xCE'u8, 0x21'u8, - 0x6C'u8, 0x83'u8, 0xDB'u8, 0x34'u8, 0x6B'u8, 0x84'u8, 0xDC'u8, 0x33'u8, - 0x62'u8, 0x8D'u8, 0xD5'u8, 0x3A'u8, 0x65'u8, 0x8A'u8, 0xD2'u8, 0x3D'u8, - 0x48'u8, 0xA7'u8, 0xFF'u8, 0x10'u8, 0x4F'u8, 0xA0'u8, 0xF8'u8, 0x17'u8, - 0x46'u8, 0xA9'u8, 0xF1'u8, 0x1E'u8, 0x41'u8, 0xAE'u8, 0xF6'u8, 0x19'u8, - 0x54'u8, 0xBB'u8, 0xE3'u8, 0x0C'u8, 0x53'u8, 0xBC'u8, 0xE4'u8, 0x0B'u8, - 0x5A'u8, 0xB5'u8, 0xED'u8, 0x02'u8, 0x5D'u8, 0xB2'u8, 0xEA'u8, 0x05'u8, - 0xE0'u8, 0x0F'u8, 0x57'u8, 0xB8'u8, 0xE7'u8, 0x08'u8, 0x50'u8, 0xBF'u8, - 0xEE'u8, 0x01'u8, 0x59'u8, 0xB6'u8, 0xE9'u8, 0x06'u8, 0x5E'u8, 0xB1'u8, - 0xFC'u8, 0x13'u8, 0x4B'u8, 0xA4'u8, 0xFB'u8, 0x14'u8, 0x4C'u8, 0xA3'u8, - 0xF2'u8, 0x1D'u8, 0x45'u8, 0xAA'u8, 0xF5'u8, 0x1A'u8, 0x42'u8, 0xAD'u8, - 0xD8'u8, 0x37'u8, 0x6F'u8, 0x80'u8, 0xDF'u8, 0x30'u8, 0x68'u8, 0x87'u8, - 0xD6'u8, 0x39'u8, 0x61'u8, 0x8E'u8, 0xD1'u8, 0x3E'u8, 0x66'u8, 0x89'u8, - 0xC4'u8, 0x2B'u8, 0x73'u8, 0x9C'u8, 0xC3'u8, 0x2C'u8, 0x74'u8, 0x9B'u8, - 0xCA'u8, 0x25'u8, 0x7D'u8, 0x92'u8, 0xCD'u8, 0x22'u8, 0x7A'u8, 0x95'u8, - 0x90'u8, 0x7F'u8, 0x27'u8, 0xC8'u8, 0x97'u8, 0x78'u8, 0x20'u8, 0xCF'u8, - 0x9E'u8, 0x71'u8, 0x29'u8, 0xC6'u8, 0x99'u8, 0x76'u8, 0x2E'u8, 0xC1'u8, - 0x8C'u8, 0x63'u8, 0x3B'u8, 0xD4'u8, 0x8B'u8, 0x64'u8, 0x3C'u8, 0xD3'u8, - 0x82'u8, 0x6D'u8, 0x35'u8, 0xDA'u8, 0x85'u8, 0x6A'u8, 0x32'u8, 0xDD'u8, - 0xA8'u8, 0x47'u8, 0x1F'u8, 0xF0'u8, 0xAF'u8, 0x40'u8, 0x18'u8, 0xF7'u8, - 0xA6'u8, 0x49'u8, 0x11'u8, 0xFE'u8, 0xA1'u8, 0x4E'u8, 0x16'u8, 0xF9'u8, - 0xB4'u8, 0x5B'u8, 0x03'u8, 0xEC'u8, 0xB3'u8, 0x5C'u8, 0x04'u8, 0xEB'u8, - 0xBA'u8, 0x55'u8, 0x0D'u8, 0xE2'u8, 0xBD'u8, 0x52'u8, 0x0A'u8, 0xE5'u8 - ] - -type - TwofishContext[bits: static[uint]] = object - S: array[4, array[256, uint32]] - K: array[40, uint32] - - twofish128* = TwofishContext[128] - twofish192* = TwofishContext[192] - twofish256* = TwofishContext[256] - twofish* = twofish128 | twofish192 | twofish256 - -template bn(x, n: uint32): byte = - cast[byte]((x shr (n * 8)) and 0xFF'u32) -template b0(x: uint32): byte = - cast[byte](x) -template b1(x: uint32): byte = - cast[byte](x shr 8) -template b2(x: uint32): byte = - cast[byte](x shr 16) -template b3(x: uint32): byte = - cast[byte](x shr 24) - -template BYTEARRAY_TO_U32(arr): uint32 = - ((cast[uint32](arr[0]) shl 24) xor (cast[uint32](arr[1]) shl 16) xor - (cast[uint32](arr[2]) shl 8) xor (cast[uint32](arr[3]))) -template BYTES_TO_U32(r0, r1, r2, r3): uint32 = - ((cast[uint32](r0) shl 24) xor (cast[uint32](r1) shl 16) xor - (cast[uint32](r2) shl 8) xor (cast[uint32](r3))) - -proc polyMult(a, b: uint32): uint32 = - result = 0'u32 - var va = a - var vb = b - while va != 0: - if (va and 1) != 0: result = result xor vb - vb = vb shl 1 - va = va shr 1 - -proc gfMod(t, modulus: uint32): uint32 = - var vmodulus = modulus shl 7 - result = t - for i in 0..<8: - var tt = result xor vmodulus - if tt < result: result = tt - vmodulus = vmodulus shr 1 - -template gfMult(a, b, modulus: uint32): uint32 = - gfMod(polyMult(a, b), modulus) - -proc rsMatrixMultiply(sd: array[8, byte]): uint32 = - var res = [0'u32, 0'u32, 0'u32, 0'u32] - for j in 0..<4: - var t = 0'u32 - for k in 0..<8: - t = t xor gfMult(RS[j][k], sd[k], RS_MOD) - res[3 - j] = t - result = BYTEARRAY_TO_U32(res) - -proc h(ax: uint32, al: array[4, uint32], k: uint32): uint32 = - var y0 = b0(ax) - var y1 = b1(ax) - var y2 = b2(ax) - var y3 = b3(ax) - - if k == 4: - y0 = Q1[y0] xor b0(al[3]) - y1 = Q0[y1] xor b1(al[3]) - y2 = Q0[y2] xor b2(al[3]) - y3 = Q1[y3] xor b3(al[3]) - if k == 4 or k == 3: - y0 = Q1[y0] xor b0(al[2]) - y1 = Q1[y1] xor b1(al[2]) - y2 = Q0[y2] xor b2(al[2]) - y3 = Q0[y3] xor b3(al[2]) - if k == 4 or k == 3 or k == 2: - y0 = Q1[Q0[Q0[y0] xor b0(al[1])] xor b0(al[0])] - y1 = Q0[Q0[Q1[y1] xor b1(al[1])] xor b1(al[0])] - y2 = Q1[Q1[Q0[y2] xor b2(al[1])] xor b2(al[0])] - y3 = Q0[Q1[Q1[y3] xor b3(al[1])] xor b3(al[0])] - - var z0 = multEF[y0] xor y1 xor multEF[y2] xor mult5B[y3] - var z1 = multEF[y0] xor mult5B[y1] xor y2 xor multEF[y3] - var z2 = mult5B[y0] xor multEF[y1] xor multEF[y2] xor y3 - var z3 = y0 xor multEF[y1] xor mult5B[y2] xor mult5B[y3] - - result = BYTES_TO_U32(z0, z1, z2, z3) - -proc fullKey(al: array[4, uint32], k: int32, - QF: var array[4, array[256, uint32]]) = - for i in 0..<256: - var y0 = byte(i) - var y1 = byte(i) - var y2 = byte(i) - var y3 = byte(i) - - if k == 4: - y0 = Q1[y0] xor b0(al[3]) - y1 = Q0[y1] xor b1(al[3]) - y2 = Q0[y2] xor b2(al[3]) - y3 = Q1[y3] xor b3(al[3]) - if k == 4 or k == 3: - y0 = Q1[y0] xor b0(al[2]) - y1 = Q1[y1] xor b1(al[2]) - y2 = Q0[y2] xor b2(al[2]) - y3 = Q0[y3] xor b3(al[2]) - if k == 4 or k == 3 or k == 2: - y0 = Q1[Q0[Q0[y0] xor b0(al[1])] xor b0(al[0])] - y1 = Q0[Q0[Q1[y1] xor b1(al[1])] xor b1(al[0])] - y2 = Q1[Q1[Q0[y2] xor b2(al[1])] xor b2(al[0])] - y3 = Q0[Q1[Q1[y3] xor b3(al[1])] xor b3(al[0])] - - QF[0][i] = ((multEF[y0].uint32 shl 24) or - (multEF[y0].uint32 shl 16) or - (mult5B[y0].uint32 shl 8) or - uint32(y0)) - QF[1][i] = ((y1.uint32 shl 24'u32) or - (mult5B[y1].uint32 shl 16) or - (multEF[y1].uint32 shl 8) or - (multEF[y1].uint32)) - QF[2][i] = ((multEF[y2].uint32 shl 24) or - (y2.uint32 shl 16) or - (multEF[y2].uint32 shl 8) or - (mult5B[y2].uint32)) - QF[3][i] = ((mult5B[y3].uint32 shl 24) or - (multEF[y3].uint32 shl 16) or - (y3.uint32 shl 8) or - mult5B[y3].uint32) - -# fully keyed h (aka g) function -template fkh(S, X): uint32 = - (S[0][b0(X)] xor S[1][b1(X)] xor S[2][b2(X)] xor S[3][b3(X)]) - -template ENC_ROUND(CTX, R0, R1, R2, R3, round) = - T0 = fkh(CTX.S, R0) - T1 = fkh(CTX.S, ROL(R1, 8)) - R2 = ROR(R2 xor (T1 + T0 + CTX.K[2 * round + 8]), 1) - R3 = ROL(R3, 1) xor (2'u32 * T1 + T0 + CTX.K[2 * round + 9]) - -template DEC_ROUND(CTX, R0, R1, R2, R3, round) = - T0 = fkh(CTX.S, R0) - T1 = fkh(CTX.S, ROL(R1, 8)) - R2 = ROL(R2, 1) xor (T0 + T1 + CTX.K[2 * round + 8]) - R3 = ROR(R3 xor (T0 + 2'u32 * T1 + CTX.K[2 * round + 9]), 1) - -proc twofishEncrypt(ctx: var TwofishContext, inp: ptr byte, oup: ptr byte) = - var T0, T1: uint32 - - var r3 = ctx.K[3] xor BSWAP(GET_DWORD(inp, 3)) - var r2 = ctx.K[2] xor BSWAP(GET_DWORD(inp, 2)) - var r1 = ctx.K[1] xor BSWAP(GET_DWORD(inp, 1)) - var r0 = ctx.K[0] xor BSWAP(GET_DWORD(inp, 0)) - - ENC_ROUND(ctx, r0, r1, r2, r3, 0) - ENC_ROUND(ctx, r2, r3, r0, r1, 1) - ENC_ROUND(ctx, r0, r1, r2, r3, 2) - ENC_ROUND(ctx, r2, r3, r0, r1, 3) - ENC_ROUND(ctx, r0, r1, r2, r3, 4) - ENC_ROUND(ctx, r2, r3, r0, r1, 5) - ENC_ROUND(ctx, r0, r1, r2, r3, 6) - ENC_ROUND(ctx, r2, r3, r0, r1, 7) - ENC_ROUND(ctx, r0, r1, r2, r3, 8) - ENC_ROUND(ctx, r2, r3, r0, r1, 9) - ENC_ROUND(ctx, r0, r1, r2, r3, 10) - ENC_ROUND(ctx, r2, r3, r0, r1, 11) - ENC_ROUND(ctx, r0, r1, r2, r3, 12) - ENC_ROUND(ctx, r2, r3, r0, r1, 13) - ENC_ROUND(ctx, r0, r1, r2, r3, 14) - ENC_ROUND(ctx, r2, r3, r0, r1, 15) - - SET_DWORD(oup, 3, BSWAP(r1 xor ctx.K[7])) - SET_DWORD(oup, 2, BSWAP(r0 xor ctx.K[6])) - SET_DWORD(oup, 1, BSWAP(r3 xor ctx.K[5])) - SET_DWORD(oup, 0, BSWAP(r2 xor ctx.K[4])) - -proc twofishDecrypt(ctx: var TwofishContext, inp: ptr byte, oup: ptr byte) = - var T0, T1: uint32 - - var r3 = ctx.K[7] xor BSWAP(GET_DWORD(inp, 3)) - var r2 = ctx.K[6] xor BSWAP(GET_DWORD(inp, 2)) - var r1 = ctx.K[5] xor BSWAP(GET_DWORD(inp, 1)) - var r0 = ctx.K[4] xor BSWAP(GET_DWORD(inp, 0)) - - DEC_ROUND(ctx, r0, r1, r2, r3, 15) - DEC_ROUND(ctx, r2, r3, r0, r1, 14) - DEC_ROUND(ctx, r0, r1, r2, r3, 13) - DEC_ROUND(ctx, r2, r3, r0, r1, 12) - DEC_ROUND(ctx, r0, r1, r2, r3, 11) - DEC_ROUND(ctx, r2, r3, r0, r1, 10) - DEC_ROUND(ctx, r0, r1, r2, r3, 9) - DEC_ROUND(ctx, r2, r3, r0, r1, 8) - DEC_ROUND(ctx, r0, r1, r2, r3, 7) - DEC_ROUND(ctx, r2, r3, r0, r1, 6) - DEC_ROUND(ctx, r0, r1, r2, r3, 5) - DEC_ROUND(ctx, r2, r3, r0, r1, 4) - DEC_ROUND(ctx, r0, r1, r2, r3, 3) - DEC_ROUND(ctx, r2, r3, r0, r1, 2) - DEC_ROUND(ctx, r0, r1, r2, r3, 1) - DEC_ROUND(ctx, r2, r3, r0, r1, 0) - - SET_DWORD(oup, 3, BSWAP(r1 xor ctx.K[3])) - SET_DWORD(oup, 2, BSWAP(r0 xor ctx.K[2])) - SET_DWORD(oup, 1, BSWAP(r3 xor ctx.K[1])) - SET_DWORD(oup, 0, BSWAP(r2 xor ctx.K[0])) - -proc initTwofishContext(ctx: var TwofishContext, N: int, key: ptr byte) = - var - A, B: uint32 - - var Mo = [0'u32, 0'u32, 0'u32, 0'u32] - var Me = [0'u32, 0'u32, 0'u32, 0'u32] - var S = [0'u32, 0'u32, 0'u32, 0'u32] - var vector = [0'u8, 0'u8, 0'u8, 0'u8, 0'u8, 0'u8, 0'u8, 0'u8] - let k = (N + 63) div 64 - - for i in 0..= ctx.sizeKey()) - initTwofishContext(ctx, ctx.bits, unsafeAddr key[0]) - -proc clear*(ctx: var TwofishContext) {.inline.} = - burnMem(ctx) - -proc encrypt*(ctx: var TwofishContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - twofishEncrypt(ctx, inbytes, outbytes) - -proc decrypt*(ctx: var TwofishContext, inbytes: ptr byte, - outbytes: ptr byte) {.inline.} = - twofishDecrypt(ctx, inbytes, outbytes) - -proc encrypt*(ctx: var TwofishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - twofishEncrypt(ctx, unsafeAddr input[0], addr output[0]) - -proc decrypt*(ctx: var TwofishContext, input: openarray[byte], - output: var openarray[byte]) {.inline.} = - assert(len(input) == ctx.sizeBlock) - assert(len(input) <= len(output)) - twofishDecrypt(ctx, unsafeAddr input[0], addr output[0]) diff --git a/src/blobsets/priv/nimcrypto/utils.nim b/src/blobsets/priv/nimcrypto/utils.nim deleted file mode 100644 index eaa6405..0000000 --- a/src/blobsets/priv/nimcrypto/utils.nim +++ /dev/null @@ -1,227 +0,0 @@ -# -# -# NimCrypto -# (c) Copyright 2016 Eugene Kabanov -# -# See the file "LICENSE", included in this -# distribution, for details about the copyright. -# - -## This module provides utility functions common to all other submodules of nimcrypto. - -{.deadCodeElim:on.} - -proc ROL*[T: uint32|uint64](x: T, n: int): T {.inline.} = - when T is uint32: - result = (x shl T(n and 0x1F)) or (x shr T(8 * sizeof(T) - (n and 0x1F))) - else: - result = (x shl T(n and 0x3F)) or (x shr T(8 * sizeof(T) - (n and 0x3F))) - -proc ROR*[T: uint32|uint64](x: T, n: int): T {.inline.} = - when T is uint32: - result = (x shr T(n and 0x1F)) or (x shl T(8 * sizeof(T) - (n and 0x1F))) - else: - result = (x shr T(n and 0x3F)) or (x shl T(8 * sizeof(T) - (n and 0x3F))) - -template GETU32*(p, o): uint32 = - (cast[uint32](cast[ptr byte](cast[uint](p) + o)[]) shl 24) xor - (cast[uint32](cast[ptr byte](cast[uint](p) + (o + 1))[]) shl 16) xor - (cast[uint32](cast[ptr byte](cast[uint](p) + (o + 2))[]) shl 8) xor - (cast[uint32](cast[ptr byte](cast[uint](p) + (o + 3))[])) - -template GETU64*(p, o): uint64 = - (cast[uint64](cast[ptr byte](cast[uint](p) + o)[]) shl 56) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 1))[]) shl 48) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 2))[]) shl 40) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 3))[]) shl 32) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 4))[]) shl 24) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 5))[]) shl 16) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 6))[]) shl 8) xor - (cast[uint64](cast[ptr byte](cast[uint](p) + (o + 7))[])) - -template PUTU32*(p, o, v) = - cast[ptr byte](cast[uint](p) + o)[] = cast[byte](v shr 24) - cast[ptr byte](cast[uint](p) + o + 1)[] = cast[byte](v shr 16) - cast[ptr byte](cast[uint](p) + o + 2)[] = cast[byte](v shr 8) - cast[ptr byte](cast[uint](p) + o + 3)[] = cast[byte](v) - -template PUTU64*(p, o, v) = - cast[ptr byte](cast[uint](p) + o)[] = cast[byte](v shr 56) - cast[ptr byte](cast[uint](p) + o + 1)[] = cast[byte](v shr 48) - cast[ptr byte](cast[uint](p) + o + 2)[] = cast[byte](v shr 40) - cast[ptr byte](cast[uint](p) + o + 3)[] = cast[byte](v shr 32) - cast[ptr byte](cast[uint](p) + o + 4)[] = cast[byte](v shr 24) - cast[ptr byte](cast[uint](p) + o + 5)[] = cast[byte](v shr 16) - cast[ptr byte](cast[uint](p) + o + 6)[] = cast[byte](v shr 8) - cast[ptr byte](cast[uint](p) + o + 7)[] = cast[byte](v) - -when cpuEndian == bigEndian: - template BSWAP*[T: uint32|uint64](x: T): T = - when T is uint32: - ((ROR(x, 8) and 0xFF00FF00'u32) or (ROL(x, 8) and 0x00FF00FF'u32)) - else: - ((x shl 56) or - ((x shl 40) and 0xFF000000000000'u64) or - ((x shl 24) and 0xFF0000000000'u64) or - ((x shl 8) and 0xFF00000000'u64) or - ((x shr 8) and 0xFF000000'u64) or - ((x shr 24) and 0xFF0000'u64) or - ((x shr 40) and 0xFF00'u64) or - (x shr 56)) - template LSWAP*[T: uint32|uint64](x: T): T = - x - template EGETU32*(p, o): uint32 = - cast[ptr uint32]((cast[uint](p) + cast[uint](o)))[] - template EPUTU32*(p, o, v) = - cast[ptr uint32]((cast[uint](p) + cast[uint](o)))[] = v - template EGETU64*(p, o): uint64 = - cast[ptr uint64]((cast[uint](p) + cast[uint](o)))[] - template EPUTU64*(p, o, v) = - cast[ptr uint64]((cast[uint](p) + cast[uint](o)))[] = v -else: - template BSWAP*[T: uint32|uint64](x: T): T = - x - template LSWAP*[T: uint32|uint64](x: T): T = - when T is uint32: - ((ROR(x, 8) and 0xFF00FF00'u32) or (ROL(x, 8) and 0x00FF00FF'u32)) - else: - ((x shl 56) or - ((x shl 40) and 0xFF000000000000'u64) or - ((x shl 24) and 0xFF0000000000'u64) or - ((x shl 8) and 0xFF00000000'u64) or - ((x shr 8) and 0xFF000000'u64) or - ((x shr 24) and 0xFF0000'u64) or - ((x shr 40) and 0xFF00'u64) or - (x shr 56)) - template EGETU32*(p, o): uint32 = - GETU32(p, o) - template EPUTU32*(p, o, v) = - PUTU32(p, o, v) - template EGETU64*(p, o): uint64 = - GETU64(p, o) - template EPUTU64*(p, o, v) = - PUTU64(p, o, v) - -template GET_DWORD*(p: ptr byte, i: int): uint32 = - cast[ptr uint32](cast[uint](p) + cast[uint](sizeof(uint32) * i))[] - -template SET_DWORD*(p: ptr byte, i: int, v: uint32) = - cast[ptr uint32](cast[uint](p) + cast[uint](sizeof(uint32) * i))[] = v - -template GET_QWORD*(p: ptr byte, i: int): uint64 = - cast[ptr uint64](cast[uint](p) + cast[uint](sizeof(uint64) * i))[] - -template SET_QWORD*(p: ptr byte, i: int, v: uint64) = - cast[ptr uint64](cast[uint](p) + cast[uint](sizeof(uint64) * i))[] = v - -template GETU8*(p, o): byte = - cast[ptr byte](cast[uint](p) + cast[uint](o))[] - -template PUTU8*(p, o, v) = - cast[ptr byte](cast[uint](p) + cast[uint](o))[] = v - -proc hexToBytes*(a: string, result: var openarray[byte]) = - doAssert(len(a) == 2 * len(result)) - var i = 0 - var k = 0 - var r = 0 - if len(a) > 0: - while i < len(a): - let c = a[i] - if i != 0 and i %% 2 == 0: - result[k] = r.byte - r = 0 - inc(k) - else: - r = r shl 4 - case c - of 'a'..'f': - r = r or (10 + ord(c) - ord('a')) - of 'A'..'F': - r = r or (10 + ord(c) - ord('A')) - of '0'..'9': - r = r or (ord(c) - ord('0')) - else: - doAssert(false) - inc(i) - result[k] = r.byte - -proc fromHex*(a: string): seq[byte] = - doAssert(len(a) %% 2 == 0) - if len(a) == 0: - result = newSeq[byte]() - else: - result = newSeq[byte](len(a) div 2) - hexToBytes(a, result) - -proc hexChar*(c: byte, lowercase: bool = false): string = - var alpha: int - if lowercase: - alpha = ord('a') - else: - alpha = ord('A') - result = newString(2) - let t1 = ord(c) shr 4 - let t0 = ord(c) and 0x0F - case t1 - of 0..9: result[0] = chr(t1 + ord('0')) - else: result[0] = chr(t1 - 10 + alpha) - case t0: - of 0..9: result[1] = chr(t0 + ord('0')) - else: result[1] = chr(t0 - 10 + alpha) - -proc toHex*(a: openarray[byte], lowercase: bool = false): string = - result = "" - for i in a: - result = result & hexChar(i, lowercase) - -proc stripSpaces*(s: string): string = - result = "" - let allowed:set[char] = {'A'..'Z', 'a'..'z', '0'..'9'} - for i in s: - if i in allowed: - result &= i - -proc burnMem*(p: pointer, size: Natural) = - var sp {.volatile.} = cast[ptr byte](p) - var c = size - if not isNil(sp): - zeroMem(p, size) - while c > 0: - sp[] = 0 - sp = cast[ptr byte](cast[uint](sp) + 1) - dec(c) - -proc burnArray*[T](a: var openarray[T]) {.inline.} = - if len(a) > 0: - burnMem(addr a[0], len(a) * sizeof(T)) - -template burnMem*[T](a: var seq[T]) = - burnArray(a) - -template burnMem*[A, B](a: var array[A, B]) = - burnArray(a) - -proc burnMem*[T](a: var T) {.inline.} = - burnMem(addr a, sizeof(T)) - -proc isFullZero*(p: pointer, size: Natural): bool = - result = true - var counter = 0 - var sp {.volatile.} = cast[ptr byte](p) - var c = size - if not isNil(sp): - while c > 0: - if sp[] != 0'u8: - counter += 1 - sp = cast[ptr byte](cast[uint](sp) + 1) - dec(c) - result = (counter == 0) - -proc isFullZero*[T](a: openarray[T]): bool {.inline.} = - result = true - if len(a) > 0: - result = isFullZero(unsafeAddr a[0], len(a) * sizeof(T)) - -proc isFullZero*[T](a: T): bool {.inline.} = - result = isFullZero(unsafeAddr a, sizeof(T)) diff --git a/tests/test_http.nim b/tests/test_http.nim index f23d917..ead54b2 100644 --- a/tests/test_http.nim +++ b/tests/test_http.nim @@ -42,12 +42,11 @@ suite "store": let name = $i blob = waitFor client.ingest(newString(i)) - echo "insert ", blob, " ", i bs = waitFor insert(client, bs, name, blob, i) setId = (waitFor commit(client, bs)).setId test "load": - bs = waitFor load(client, setId) + bs = waitFor client.load(setId) for i in 1..count: let name = $i @@ -69,7 +68,6 @@ suite "store": test "random": for i in 1..count: store.randomApply(bs, rng) do (id: BlobId; size: BiggestInt): - echo "randomApply: ", id, " ", size let stream = store.openBlobStream(id, size, dataBlob) close stream @@ -79,7 +77,6 @@ suite "store": let stream = newMemberStream() asyncCheck stream.streamMembers(store, bs) var - val: tuple[key: Key; id: BlobId; size: BiggestInt] found = false count = 0 while not found: @@ -91,5 +88,4 @@ suite "store": inc count check(count > 0) check(found) - echo "found ", i, " after ", count waitFor findAll() diff --git a/tests/test_set.nim b/tests/test_set.nim index f73197c..cd0b28b 100644 --- a/tests/test_set.nim +++ b/tests/test_set.nim @@ -1,16 +1,44 @@ +import base32 +import ../src/blobsets, ../src/blobsets/filestores import std/asyncdispatch, std/unittest, std/os, std/parseopt -import ../src/blobsets +suite "Encoding": + var empty: BlobId + test $empty: + check empty.toBase32 == base32.encode(cast[array[digestSize,char]](empty.data), pad=false) + check toBlobId($empty).data == empty.data + check empty.toBase32.toBlobId.data == empty.data + check empty.toHex.toBlobId.data == empty.data + +suite "THEX": + let store = newNullStore() + proc testThex(data: string): string = + writeFile "tmp", data + let (id, _) = waitFor store.ingestFile("tmp") + removeFile "tmp" + id.toBase32 + + test "The empty (zero-length) file": + check testThex("") == "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ" + + test "A file with a single zero byte": + check testThex("\0") == "VK54ZIEEVTWNAUI5D5RDFIL37LX2IQNSTAXFKSA" + + test "A file with 1024 'A' characters": + var s = newString(1024) + for c in s.mitems: c = 'A' + check testThex(s) == "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA" + + test "A file with 1025 'A' characters": + var s = newString(1025) + for c in s.mitems: c = 'A' + check testThex(s) == "PZMRYHGY6LTBEH63ZWAHDORHSYTLO4LEFUIKHWY" suite "Blob set tests": - var store = newNullStore() randomCid = blobHash("") - # test "zero blob": - # check(randomCid == zeroChunk) - proc randomize() = randomCid = blobHash(randomCid.toHex)