Skip to content

Instantly share code, notes, and snippets.

@maximilliangeorge
Last active December 27, 2017 16:23
Show Gist options
  • Save maximilliangeorge/df75f8906bdb522cdb125af76c806c87 to your computer and use it in GitHub Desktop.
Save maximilliangeorge/df75f8906bdb522cdb125af76c806c87 to your computer and use it in GitHub Desktop.
PoC REST API authorization

One of the coolest things about bitcoin is that identities/accounts aren't really registered anywhere. In a sense, every possible identity already exists, mathematically. This allows for some interesting approaches to UX that are different in crypto than in other ecosystems.

Here's is a simple example of an API that uses the user's public key as the endpoint. It requires each request to be signed using the user's private key.

Dependencies: NodeJS, bcoin, restler, express

Similar projects: Bitauth, BitID

const rest = require('restler');
// Create keypair
keys.master = await bcoin.hd.generate();
keys.key = keys.master.derivePath('m/44/0/0/0/0');
keys.keyring = new bcoin.keyring(keys.key.privateKey);
// Function to create a signature for the request body
function getSignatureForBody(body, key) {
let bodyAsBuffer = Buffer.from(JSON.stringify(body));
let signature = bcoin.crypto.ecdsa.sign('secp256k1', 'sha256', bodyAsBuffer, key);
return signature.toString('hex');
}
// Make the request
let pubKey = keys.keyring.getPublicKey();
let privKey = keys.keyring.getPrivateKey();
let body = {
timestamp: Date.now().toString(), // Must be string
content: 'Hello world!'
}
rest.get('http://localhost:8080/api/v1/' + pubKey.toString('hex'), {
headers: {
'ECDSA-Auth': getSignatureForBody(body, privKey)
},
data: body,
}).on('complete', (result, response) => {
console.log(result);
});
const express = require('express');
const bcoin = require('bcoin');
// Express
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Auth middleware
function ecdsaAuthentication(req, res, next) {
let message = Buffer.from(JSON.stringify(req.body));
let signature = Buffer.from(req.headers['ecdsa-auth'], 'hex');
let pubKey = Buffer.from(req.params.pubKey, 'hex');
if (bcoin.crypto.ecdsa.verify('secp256k1', 'sha256', message, signature, pubKey)) {
// Signature OK
next();
} else {
// Bad signature
res.status(401).json('unauthorized');
}
}
// Accept GET requests using public key as endpoint
app.get('/api/v1/:pubKey', ecdsaAuthentication, function(req, res) {
res.status(200).json('authorized');
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment