Giter VIP home page Giter VIP logo

keyfender's Introduction

⚠️ This project was the Proof-of-Concept implementation for what is now available as the Nitrokey NetHSM. ⚠️

keyfender Unikernel

Build Status

Demo

A simple demo case - nginx with pkcs#11 driver using a keyfender instance for private key storage - is available here.

Container

To easily try out keyfender, use the docker container keyfender/keyfender:

Run it as a real kvm VM instance:

$ docker run --rm -ti --device=/dev/kvm:/dev/kvm --device=/dev/net/tun:/dev/net/tun --cap-add=NET_ADMIN -p4433:4433 keyfender/keyfender

If kvm is not available, you can run it as a normal unix process on a tap device:

$ docker run --rm -ti --device=/dev/net/tun:/dev/net/tun --cap-add=NET_ADMIN -p4433:4433 keyfender/keyfender

If even tap devices are not available, you can run it on a normal network socket:

$ docker run --rm -ti -p4433:4433 keyfender/keyfender

Prerequisites

Install OCaml and MirageOS.

Install the following dependencies:

opam pin add irmin-http https://github.com/mirage/irmin.git

Building

On Unix, do:

$ make configure
$ make depend
$ make build
$ make run

This will run the HSM on localhost on port 8080, so you should be able to access http://localhost:8080/api/v0.

For debug output start keyfender by executing MIRAGE_LOGS=debug ./src/keyfender.

For a Xen DHCP kernel, do:

$ DHCP=true MODE=xen NET=direct make configure
$ make build

edit keyfender.xl to add a VIF, e.g. via:

vif = ['bridge=xenbr0']

And then run the VM via xl create -c keyfender.xl

API

The API is described in "docs" folder. You can view it in the browser here.

Tutorial

First, let's see what we have here:

$ curl -i -w "\n" -X GET localhost:8080/api/v0/system/information
HTTP/1.1 200 OK
{"vendor":"keyfender","product":"keyfender","version":"0.1"}

See what the device's status is:

$ curl -i -w "\n" -X GET localhost:8080/api/v0/system/status

HTTP/1.1 200 OK
{"status":"ok"}

Does it has some keys on it?

$ curl -i -w "\n" -X GET localhost:8080/api/v0/keys

HTTP/1.1 401 Unauthorized

Ohh, keyfender seems to have access control. In fact is has an Admin password and a User password. The Admin password is used to authenticate any kind of changes of the system, settings and keys. The User password is required to authenticate the usage of keyfender without any modification.

Before you can do anything with the system, the Admin password needs to be defined first. It doesn't has a default value.

$ curl -i -w "\n" -X PUT localhost:8080/api/v0/system/passwords/admin -H "content-type: application/json" -d '{ newPassword: "secret" }'

HTTP/1.1 200 OK
{ "status": "success" }

If you want to change the Admin password again, you need to authenticate:

$ curl -i -w "\n" -X PUT http://admin:secret@localhost:8080/api/v0/system/passwords/admin -H "content-type: application/json" -d '{ newPassword: "supersecret" }'

HTTP/1.1 200 OK
{ "status": "success" }

Define a User password:

$ curl -i -w "\n" -X PUT http://admin:supersecret@localhost:8080/api/v0/system/passwords/user -H "content-type: application/json" -d '{ newPassword: "usersecret" }'

HTTP/1.1 200 OK
{ "status": "success" }

You can generate RSA keys:

$ curl -i -w "\n" -X POST http://admin:supersecret@localhost:8080/api/v0/keys -H "content-type: application/json" -d '{"purpose":"signing", "algorithm":"RSA", "length":4096}'

HTTP/1.1 200 OK
{
  "status": "success",
  "data": {
    "location": "/api/v0/keys/Im4bPvqXM8w4SZxEvxvi"
  }
}

Here you got the location of the newly generated key. The last part of the URL is the key ID: Im4bPvqXM8w4SZxEvxvi

Instead of dealing with generated key IDs, you can specify the key ID yourself:

$ curl -i -w "\n" -X POST http://admin:supersecret@localhost:8080/api/v0/keys -H "content-type: application/json" -d '{"purpose":"authentication", "algorithm":"RSA", "length":2048, "id":"myKey"}'

HTTP/1.1 200 OK
{
  "status": "success",
  "data": {
    "location": "/api/v0/keys/myKey"
  }
}

You can also import existing keys:

$ curl -i -w "\n" -X POST http://admin:supersecret@localhost:8080/api/v0/keys -d '{"purpose":"encryption", "algorithm":"RSA", "privateKey":{"publicExponent":"AQAB","primeP":"4P7TWJety3bZ47tp_WnB8BEbBX9kd_ONa6bOnPd2nxfXmLl1W61yQbZAw8bTReBfYsre8wYe8jVSs-nNGgR19-FPnXMg8xAgFrdcVvfj8OverK-q3MJhZTT2X-ZAhN5H-wWf_xXPJPMtPsPXXs914fU7WchZoBIVcarQq0eGHMM=","primeQ":"x8QUQ4aPrh33oBip_PBpzRHMRtg4isr8CwXQq8ijSd8dvYjaC8mTYPB0Nytsi047XjXBLq0HyvpjxpcVWYBzqrPKFFcafTdk80SQNtD5EUyGy_rFRbowDaG5UoMVSL1VrJLx6xI8OToUP2J1ZiuZG0I-Ms2YQcanZzYRANppLYM="}}'

HTTP/1.1 200 OK
{
  "status": "success",
  "data": {
    "location": "/api/v0/keys/kfG8H2z2cddUMXeiK5Ky"
  }
}

You can overwrite an existing key with PUT or delete with DELETE.

Now we are going to perform key operations. For this we don't need the Admin password anymore but can use the User password instead. What we have got?

$ curl -i -w "\n" -X GET http://user:usersecret@localhost:8080/api/v0/keys

HTTP/1.1 200 OK
content-length: 199
content-type: application/json
vary: Accept, Accept-Encoding, Accept-Charset, Accept-Language

{
  "status": "success",
  "data": [
    { "location": "/api/v0/keys/cphQSDP1n2q4BxnPVI4y" },
    { "location": "/api/v0/keys/kfG8H2z2cddUMXeiK5Ky" },
    { "location": "/api/v0/keys/myKey" }
  ]
}

Here is how you get a public key:

$ curl -i -w "\n" -X GET http://user:usersecret@localhost:8080/api/v0/keys/kfG8H2z2cddUMXeiK5Ky
HTTP/1.1 200 OK
content-length: 558
content-type: application/json
vary: Accept, Accept-Encoding, Accept-Charset, Accept-Language

{
  "status": "success",
  "data": {
    "id": "kfG8H2z2cddUMXeiK5Ky",
    "purpose": "encryption",
    "algorithm": "RSA",
    "publicKey": {
      "modulus":
        "r5JrMu80IEJoyM-9utzBs64Her9-VkjYhTU9a5ZrQ0zbECFYpdcTScRrWkZHy0Of6OLXumHHK_Krikmq1m53iw88iTVB_Up8oREkZt2szWifJlAVse9vfzERC_VmIFVqqZgmY1JopygVJ5_MMniOe8fN3iZAf-33ZB1aL14f0Y4m6xGXSN8er_q1yxevWy5oUVyF8Zl7r3ATERAX_9lsuLTZN9tAEBFqq4naH9mSsEsyRljybSuhX411CWUE4cj8JXf9qKumoN7duYNTjipSZqLauJ56txn5zTKDMGKvpcxB5jlQ_0ltVcGEayIjkXhJFR_dM2uwG4cQSmC4Bqn-yQ==",
      "publicExponent": "AQAB"
    }
  }
}

You can get it also in PEM format:

$ curl -i -w "\n" -X GET http://user:usersecret@localhost:8080/api/v0/keys/kfG8H2z2cddUMXeiK5Ky/public.pem

HTTP/1.1 200 OK
content-length: 451
content-type: application/x-pem-file
vary: Accept, Accept-Encoding, Accept-Charset, Accept-Language

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr5JrMu80IEJoyM+9utzB
s64Her9+VkjYhTU9a5ZrQ0zbECFYpdcTScRrWkZHy0Of6OLXumHHK/Krikmq1m53
iw88iTVB/Up8oREkZt2szWifJlAVse9vfzERC/VmIFVqqZgmY1JopygVJ5/MMniO
e8fN3iZAf+33ZB1aL14f0Y4m6xGXSN8er/q1yxevWy5oUVyF8Zl7r3ATERAX/9ls
uLTZN9tAEBFqq4naH9mSsEsyRljybSuhX411CWUE4cj8JXf9qKumoN7duYNTjipS
ZqLauJ56txn5zTKDMGKvpcxB5jlQ/0ltVcGEayIjkXhJFR/dM2uwG4cQSmC4Bqn+
yQIDAQAB
-----END PUBLIC KEY-----

With each key you can execute decrypt and signing operations (Technical restriction to the designated key purpose is not enforced yet.) Signing can invoke hashing, or you send a hash instead.

$ curl -i -w "\n" -X POST -d '{"message":"DOTvDL7e547MJ5tTWqjU5W3-wDFFh0f-g4GHbdgl7iPh6wQe53JV25nxDWgEi3HJcw5YkoBGIbj1XfRbTZbsI77lfIK_lhpf5XVqeKrU0YCRPYDZ2qDFdJyMajyjDieUwTmyxLdrJ_UrwdyFtNPQ27XvjUUF71DLTNMrbKnRNeqVoAWy3PK3Asqo62DRAwLvwRuuz6UhmoDNdJdVzHCi8KJdNQHI5Q8Nhn2SAwVO85IRceOrzIoU00l2QmR0WGNtTwli1lWqfvtE21wExA9ys7mqvJpUCUzPamlsESBveh7c3FboTkekUzZlB6YOUhoWmaV8gxaMBzRFKqKBulbJ8Q=="}' http://user:usersecret@localhost:8080/api/v0/keys/myKey/actions/pkcs1/sign

Decrypting data is similarly easy:

$ curl -i -w "\n" -X POST -d '{"encrypted":"DOTvDL7e547MJ5tTWqjU5W3-wDFFh0f-g4GHbdgl7iPh6wQe53JV25nxDWgEi3HJcw5YkoBGIbj1XfRbTZbsI77lfIK_lhpf5XVqeKrU0YCRPYDZ2qDFdJyMajyjDieUwTmyxLdrJ_UrwdyFtNPQ27XvjUUF71DLTNMrbKnRNeqVoAWy3PK3Asqo62DRAwLvwRuuz6UhmoDNdJdVzHCi8KJdNQHI5Q8Nhn2SAwVO85IRceOrzIoU00l2QmR0WGNtTwli1lWqfvtE21wExA9ys7mqvJpUCUzPamlsESBveh7c3FboTkekUzZlB6YOUhoWmaV8gxaMBzRFKqKBulbJ8Q=="}' http://user:usersecret@localhost:8080/api/v0/keys/myKey/actions/decrypt

Available key actions:

  • decrypt
  • pkcs1/decrypt
  • oaep/md5/decrypt
  • oaep/sha1/decrypt
  • oaep/sha224/decrypt
  • oaep/sha256/decrypt
  • oaep/sha384/decrypt
  • oaep/sha512/decrypt
  • pkcs1/sign
  • pss/sha1/sign
  • pss/sha224/sign
  • pss/sha256/sign
  • pss/sha384/sign
  • pss/sha512/sign

keyfender's People

Contributors

ansiwen avatar jans23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

mikalv

keyfender's Issues

It's possible to create different keys with same id

$ curl -i -w "\n" -X POST -k https://admin:secret@localhost:4433/api/v0/keys -H "content-type: application/json" -d '{"purpose":"authentication", "algorithm":"RSA", "length":2048, "id":"myKey"}'
HTTP/1.1 303 See Other
content-length: 23
content-type: application/json
location: /api/v0/keys/myKey
vary: Accept, Accept-Encoding, Accept-Charset, Accept-Language

{ "status": "success" }
$ [...]
$ curl -i -k -w "\n" -X GET https://admin:secret@localhost:4433/api/v0/keys
HTTP/1.1 200 OK
content-length: 209
content-type: application/json
vary: Accept, Accept-Encoding, Accept-Charset, Accept-Language

{
  "status": "success",
  "data": [
    { "location": "/api/v0/keys/myKey" },
    { "location": "/api/v0/keys/myKey" },
    { "location": "/api/v0/keys/myKey" },
    { "location": "/api/v0/keys/myKey" }
  ]
}

Admin can provide key ID

The hash should be base64url encoded.

SHA1 or SHA256 (or even half a SHA256) are possible candidates. The risks of collisions should be considered too. Ideally during key generation/import the device checks for collisions and applies a work around.

To get an impression how long those hashes are, here are examples:
SHA1: rr1MLoGs6S69oryQmso0oTn/LOo=
SHA256: LzIAkwJM9YatJW2K5BvvH+LAO3nzhU0+RQDZ524FLAk=

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.