Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add RSA builtin functions for signing (implemented in Haskell) #4932

Conversation

etorreborre
Copy link
Contributor

Overview

This PR introduces 2 new builtin functions which can be used to sign a message with a RSA private key, and verify the signature with the corresponding RSA public key.

This is best shown as a transcript:

```unison
up = 0xs0123456789abcdef
down = 0xsfedcba9876543210

-- | Generated with:
--     openssl genrsa -out private_key.pem 1024
--     openssl rsa -in private_key.pem -outform DER | xxd -p
secret = 0xs30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100a7104b2f20725896076e629ccedbcd6907b16694c6e3d8768b5e0e685670b49616e796c588e5aafb92ef986c1a42c021fed0bdc99212c969cdab98087a0ee4c2f4acd4b6049a87a96afc45668329a3cf21a86fb13b488bbe9fefa1cd5a459014f0d0101378e9661e11b73acf54c8a91141ac90309e7fb6ed69b4e63230ab291502030100010281807cdc23a4fc3619d93f8293b728af848d0c0fdd603269d5bd7b99f760a9c22065d08693dbdcddf1f5863306133d694819e04d789aef4e95343b601507b8d9eac4492e6d7031b035c5d84eceaa9686b292712632d33b3303af84314d7920bc3d45f90d7818fc2587b129196d378ee4ed3e6b8d9010d504bb6470ff53e7c5fb17a1024100d67cbcf113d24325fcef12a778dc47c7060055290b68287649ef092558daccb61c4e7bc290740b75a29d4356dcbd66d18b0860dbff394cc8ff3d94d57617adbd024100c765d8261dd3d8e0d3caf11ab7b212eed181354215687ca6387283e4f0be16e79c8f298be0a70c7734dea78ea65128517d693cabfa4c0ff5328f2abb85d2023902403ca41dc347285e65c22251b2d9bfe5e7463217e1b7e0e5f7b3a58a7f6da4c6d60220ca6ad2ee8c42e10bf77afa83ee2af6551315800e52404db1ba7fb398b43d02410084877d85c0177933ddb12a554eb8edfa8b872c85d2c2d2ee8be019280696e19469ab81bab5c371f69d4e4be1f54b45d7fbda017870f1333e0eafb78051ee8689024061f694c12e934c44b7734f62d1b2a3d3624a4980e1b8e066d78dbabd2436654fbb9d9701425900daaafa1e031310e8a580520bb9e1c1288c669fce252bad1e65

-- | Generated with:
--     openssl rsa -in private_key.pem -outform DER -pubout | xxd -p
public = 0xs30819f300d06092a864886f70d010101050003818d0030818902818100a7104b2f20725896076e629ccedbcd6907b16694c6e3d8768b5e0e685670b49616e796c588e5aafb92ef986c1a42c021fed0bdc99212c969cdab98087a0ee4c2f4acd4b6049a87a96afc45668329a3cf21a86fb13b488bbe9fefa1cd5a459014f0d0101378e9661e11b73acf54c8a91141ac90309e7fb6ed69b4e63230ab29150203010001

message = up ++ down ++ up ++ down ++ down ++ up ++ down ++ up

signature = crypto.Rsa.sign.impl secret message

sigOkay = match signature with
  Left err -> Left err
  Right sg -> crypto.Rsa.verify.impl public message sg

> signature
> sigOkay

The output is:

    21 | > signature
           ⧩
           Right
             0xs84b02b6bb0e1196b65378cb12b727f7b4b38e5979f0632e8a51cfab088827f6d3da4221788029f75a0a5f4d740372cfa590462888a1189bbd9de9b084f26116640e611af5a1a17229beec7fb2570887181bbdced8f0ebfec6cad6bdd318a616ba4f01c90e1436efe44b18417d18ce712a0763be834f8c76e0c39b2119b061373
  
    22 | > sigOkay
           ⧩
           Right true

The base library, before this PR, only contains the crypto.Ed25519.sign and crypto.Ed25519.verify functions (mentioned in this issue, which is still opened).

Implementation notes

The implementation adds two functions to the list of builtin functions, and implements them using:

  • The asn1-encoding library in order to decode both the private key and the public key as ASN1 data structures from which a PrivateKey and PublicKey can be created
  • The cryptonite library to call the underlying sign and verify functions.

Interesting/controversial decisions

Types

The signatures of those 2 functions involve untyped bytestrings but the content of those bytestrings is very specific (see the transcript above). In terms of usage inside a Unison code base it would be nice to provide better types. For example: crypto.rsa.PublicKey, crypto.rsa.PrivateKey, crypto.rsa.Signature.

Signature generation

The cryptonite library gives the possibility to create a safer signature by using a Blinder. However this requires the introduction of MonadRandom and I didn't evaluate what would be the necessary changes to support this.

Racket implementation

This should be the next step. There is already a Racket backend for the Ed25519 functions, so we could do something similar for the RSA functions.

Test coverage

The test coverage is provided by:

  • The rsa.md transcript at a high level.
  • Some unit tests for the parsing of the public and private keys.

Loose ends

The three points mentioned in "Interesting/controversial decisions" could be revisited.

@etorreborre etorreborre force-pushed the etorreborre/feat/rsa-builtins-for-haskell branch from e31ab43 to 01bb42b Compare May 10, 2024 22:05
@etorreborre etorreborre marked this pull request as ready for review May 10, 2024 22:08
@etorreborre etorreborre force-pushed the etorreborre/feat/rsa-builtins-for-haskell branch from b20a999 to d08a31b Compare May 11, 2024 15:46
@aryairani
Copy link
Contributor

Solid first PR :)

@aryairani
Copy link
Contributor

@etorreborre Could you add a test to rsa.md that tweaks a byte in the message or the signature to demonstrate a failed verification?

@etorreborre
Copy link
Contributor Author

@aryairani great idea, done.

Copy link
Contributor

@aryairani aryairani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Could you coordinate with @runarorama to add support to @unison/base once this is merged.

cc @ChrisPenner here is another new builtin you may be able to use for troubleshooting Share

@aryairani aryairani merged commit 4f4ed49 into unisonweb:trunk May 12, 2024
19 checks passed
@etorreborre
Copy link
Contributor Author

@runarorama how can I help?

@etorreborre
Copy link
Contributor Author

@runarorama actually I can see what needs to be done on the base library side. I'll do a PR when there's a new ucm release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants