ponylang / crypto

Library of common cryptographic algorithms and functions for Pony
https://ponylang.io
BSD 2-Clause "Simplified" License
11 stars 8 forks source link

Move all ffi methods to ssl.pony #36

Open damon-kwok opened 4 years ago

damon-kwok commented 4 years ago
class Digest
  """
  Produces a hash from the chunks of input. Feed the input with append() and
  produce a final hash from the concatenation of the input with final().
  """
  let _digest_size: USize
  let _ctx: Pointer[_EVPCTX]
  var _hash: (Array[U8] val | None) = None

  new md4() =>
    """
    Use the MD4 algorithm to calculate the hash.
    """
    _digest_size = 16
    ifdef "openssl_1.1.x" then
      _ctx = @EVP_MD_CTX_new[Pointer[_EVPCTX]]()
    else
      _ctx = @EVP_MD_CTX_create[Pointer[_EVPCTX]]()
    end
    @EVP_DigestInit_ex[None](_ctx, @EVP_md4[Pointer[_EVPMD]](), USize(0))

  new md5() =>
    """
    Use the MD5 algorithm to calculate the hash.
    """
    _digest_size = 16
    ifdef "openssl_1.1.x" then
      _ctx = @EVP_MD_CTX_new[Pointer[_EVPCTX]]()
    else
      _ctx = @EVP_MD_CTX_create[Pointer[_EVPCTX]]()
    end
    @EVP_DigestInit_ex[None](_ctx, @EVP_md5[Pointer[_EVPMD]](), USize(0))

  new ripemd160() =>
    """
    Use the RIPEMD160 algorithm to calculate the hash.
    """
    _digest_size = 20
    ifdef "openssl_1.1.x" then
      _ctx = @EVP_MD_CTX_new[Pointer[_EVPCTX]]()
    else
      _ctx = @EVP_MD_CTX_create[Pointer[_EVPCTX]]()
    end
    @EVP_DigestInit_ex[None](_ctx, @EVP_ripemd160[Pointer[_EVPMD]](), USize(0))

At moment, the ffi methods are spread throughout the entire library. For clean and maintainable code, we can refer to the practice of lori: https://github.com/seantallen-org/lori/blob/master/lori/pony_asio.pony

In the end it should look like this:

primitive Evp
  fun md_ctx_new(): Pointer[_MDCTX] => ...
  fun cipher_ctx_new(): Pointer[_CIPHERCTX] => ...
  fun encode_ctx_new(): Pointer[_ENCODECTX] => ...
  fun ssl_version(): String => ...
SeanTAllen commented 4 years ago

The purpose of the additional indirection in Lori is to allow for different implementations (for example for testing) to be swapped in.

Beyond some idea of "cleanliness", are there advantages around testability or something else that would come from this change?

damon-kwok commented 4 years ago

Things are artificial. If we can think of more, we can do better.

SeanTAllen commented 4 years ago

I can see moving "new"/"edit" to it's own primitive.

SeanTAllen commented 4 years ago

@damon-kwok can you give a full example of the change for the snippet of code you included for how it is right now?

It's hard to envision from your initial example what the change would be.

damon-kwok commented 4 years ago
class Digest
  """
  Produces a hash from the chunks of input. Feed the input with append() and
  produce a final hash from the concatenation of the input with final().
  """
  let _digest_size: USize
  let _ctx: Pointer[_EVPCTX]
  var _hash: (Array[U8] val | None) = None

  new md4() =>
    """
    Use the MD4 algorithm to calculate the hash.
    """
    _digest_size = 16
    _ctx = Evp.md_ctx_new()
    Evp.digest_init_ex(_ctx, EvpCmd.md_md4(), USize(0))
SeanTAllen commented 4 years ago

And what would the Evp primitive look like? What methods? And what would their implementation be?

damon-kwok commented 4 years ago
primitive Evp
  fun md_ctx_new(): Pointer[_MDCTX] => ...
  fun cipher_ctx_new(): Pointer[_CIPHERCTX] => ...
  fun encode_ctx_new(): Pointer[_ENCODECTX] => ...
  fun ssl_version(): String => ...

primitive EvpCmd
  fun md_md4(): Pointer[_EVPMD] => 
  fun md_md5(): Pointer[_EVPMD] => 
  fun cipher_aes(): Pointer[_EVPMD] => 

Or

primitive EvpMd
  fun ctx_new(): Pointer[_MDCTX] => ...
  fun md_md4(): Pointer[_EVPMD] => 
  fun md_md5(): Pointer[_EVPMD] => 

primitive EvpCipher
  fun ctx_new(): Pointer[_CIPHERCTX] => ...
  fun cmd_aes(): Pointer[_EVPMD] =>
SeanTAllen commented 4 years ago

Can you give the implementations for the methods you listed?

damon-kwok commented 4 years ago

@SeanTAllen Yes, see: https://github.com/pony-ready/crypto/tree/refactor/crypto

SeanTAllen commented 4 years ago

@damon-kwok I don't have time to figure out where in that repo I am supposed to be looking. Where specifically should I look?

damon-kwok commented 4 years ago

https://github.com/pony-ready/crypto/blob/refactor/crypto/_test.pony It contains all the hash algorithms.

SeanTAllen commented 4 years ago

@damon-kwok that isn't what I asked for an example of.