nimcrypto icon indicating copy to clipboard operation
nimcrypto copied to clipboard

Some blowfish modes don't work

Open MatthewScholefield opened this issue 4 years ago • 6 comments

I'm not sure if there's something I'm doing improperly, but I tried instantiating a CBC[blowfish] context and .init() doesn't seem to work:

import nimcrypto/blowfish
import nimcrypto/bcmode

var cbc: CBC[blowfish]
var key: string = "1234123412ABCDEF"
var iv: string = "ABCDEF1234123412"
var message: cstring = "hello"
var decrypted: cstring = cast[cstring](alloc0(100))
var encrypted: cstring = cast[cstring](alloc0(100))

cbc.init(key.toOpenArrayByte(0, key.len-1), iv.toOpenArrayByte(0, iv.len-1))

cbc.encrypt(cast[ptr byte](message), cast[ptr byte](encrypted), 100)
echo encrypted
echo cbc.decrypt(cast[ptr byte](encrypted), cast[ptr byte](decrypted), 100)
echo decrypted
dealloc(decrypted)
dealloc(encrypted)

Here's the build output:

cbcblowfishdemo.nim(37, 4) template/generic instantiation of `init` from here
nimcrypto/bcmode.nim(292, 9) template/generic instantiation of `assert` from here
nimcrypto/bcmode.nim(257, 16) Error: undeclared field: 'cipher'

This seems to result from the following function in bcmode.nim:

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)  # Error: undeclared field: 'cipher'

However, I have no idea why it can't see the cipher field (even when I try changing it to be a public member of CBC).

Any idea why it errors or if I'm initializing it improperly?

MatthewScholefield avatar Nov 30 '19 04:11 MatthewScholefield

A workaround is to edit the library to make .cipher and .iv public in the encryption mode that you are working with and then you can encrypt and decrypt data like this:

import nimcrypto
import strutils

proc encryptData*(key: string, data: string, iv: string): string =
  var ctx: CBC[blowfish]
  result = newString(len(data))
  ctx.cipher.init(key.toOpenArrayByte(0, key.len-1))
  copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock)
  ctx.encrypt(data.toOpenArrayByte(0, data.len - 1), result.toOpenArrayByte(0, result.len - 1))

proc decryptData*(key: string, data: string, iv: string): string =
  var ctx: CBC[blowfish]
  result = newString(len(data))
  ctx.cipher.init(key.toOpenArrayByte(0, key.len-1))
  copyMem(addr ctx.iv[0], unsafeAddr iv[0], ctx.sizeBlock)
  ctx.decrypt(data.toOpenArrayByte(0, data.len - 1), result.toOpenArrayByte(0, result.len - 1))

var encryptedData = encryptData("abc", "this is a test", "12345678")
var decryptedData = decryptData("abc", encryptedData, "12345678")

echo encryptedData.toHex()
echo decryptedData

So, to make this compile you would change the CBC type in bcmode.nim to contain asterisks on cipher and iv like:

  CBC*[T] = object
    cipher*: T
    iv*: array[MaxBlockBytesSize, byte]
    # ...

This also works for other types like CFB.

MatthewScholefield avatar Jan 09 '20 19:01 MatthewScholefield

Sorry, but currently Blowfish modes are not supported, mostly because of Nim's generic bugs and limitations and because Blowfish do not has fixed key size. I need some time to find proper solution to fix it, but currently i dont have enough free time.

cheatfate avatar Jan 09 '20 22:01 cheatfate

@MatthewScholefield : thanks again for your reply on gmail, i had some "python to nim" work to be done before trying your workaround. But as you noticed results are different for CBC mode between python's and nim's test. @cheatfate : your words certainly explain why the workaround is not the success we could expect. thanks for your work btw, sorry i cant help you or myself in this.

hed0n1st avatar Jan 11 '20 16:01 hed0n1st

edited @cheatfate : sorry for the inconvenience, i really didn't want to bother but give a hand on this. As i said i'd love to use your own project. I only thought you could use my work too to improve yours, spending less time on this. I was wrong. Sorry again.

hed0n1st avatar Jan 21 '20 11:01 hed0n1st

I'm closing this issue, because this is not right place for advertising of your own projects.

@hed0n1st @MatthewScholefield this issue could be reopened if author will remove ads from this issue.

cheatfate avatar Jan 21 '20 12:01 cheatfate

@cheatfate The author edited their post to remove the link. But come on, the dude just posted a link to his solution to a task that doesn't even work with your library. Let's all be friendly here. No need to get touchy about someone sharing a project that solves a current issue with a library.

MatthewScholefield avatar Jan 21 '20 15:01 MatthewScholefield