Skip to content

Instantly share code, notes, and snippets.

@lalilaloe
Created December 11, 2018 13:42
Show Gist options
  • Save lalilaloe/02ff061ce417a0866c70e0bcb708c3ac to your computer and use it in GitHub Desktop.
Save lalilaloe/02ff061ce417a0866c70e0bcb708c3ac to your computer and use it in GitHub Desktop.
EncryptRequestHandler using crypto libary
import * as forge from "node-forge";
import BunqJSClient from "../BunqJSClient";
import Session from "../Session";
import LoggerInterface from "../Interfaces/LoggerInterface";
import Request from "./Request";
var crypto = require('crypto');
import ApiAdapterOptions from "../Types/ApiAdapterOptions";
const HEADER_CLIENT_ENCRYPTION_HMAC = "X-Bunq-Client-Encryption-Hmac";
const HEADER_CLIENT_ENCRYPTION_IV = "X-Bunq-Client-Encryption-Iv";
const HEADER_CLIENT_ENCRYPTION_KEY = "X-Bunq-Client-Encryption-Key";
const AES_ENCRYPTION_METHOD = 'aes-256-cbc';
const AES_KEY_LENGTH = 32;
const HMAC_ALGORITHM = 'sha1';
const INITIATION_VECTOR_LENGTH = 16;
export default class EncryptRequestHandler {
public Session: Session;
public logger: LoggerInterface;
public BunqJSClient: BunqJSClient;
constructor(Session: Session, loggerInterface: LoggerInterface, BunqJSClient: BunqJSClient) {
this.BunqJSClient = BunqJSClient;
this.Session = Session;
this.logger = loggerInterface;
}
/**
* Signs a request using our privatekey
* @param {Request} request
* @param {ApiAdapterOptions} options
* @returns {Promise<string>}
*/
public async encryptRequest(request: Request, options: ApiAdapterOptions): Promise<void> {
const body = JSON.stringify(request.requestConfig.data);
const key = crypto.randomBytes(AES_KEY_LENGTH);
const iv = crypto.randomBytes(INITIATION_VECTOR_LENGTH);
const encryptedAesKey = new Buffer(this.encryptPublic(key, this.Session.serverPublicKey), 'binary');
const encryptedBody = new Buffer(this.encrypt(body, key, iv), 'binary');
const hmacBuffer = new Buffer(this.hmac(key, iv + encryptedBody), 'binary');
// set new body
request.setData(encryptedBody.toString('base64'));
// disable request transform
request.setOptions("transformRequest", data => {
// don't transform the data, return it directly
return data;
});
// set headers
request.setHeader("Content-Type", "multipart/form-data");
request.setHeader(HEADER_CLIENT_ENCRYPTION_HMAC, hmacBuffer.toString('base64'));
request.setHeader(HEADER_CLIENT_ENCRYPTION_IV, iv.toString('base64'));
request.setHeader(HEADER_CLIENT_ENCRYPTION_KEY, encryptedAesKey.toString('base64'));
}
private hmac(key, content) {
var hmac = crypto.createHmac(HMAC_ALGORITHM, key);
hmac.update(content);
return hmac.digest('binary');
}
private encrypt(text, key, iv) {
var cipher = crypto.createCipheriv(AES_ENCRYPTION_METHOD, key, iv)
var crypted = cipher.update(text, 'utf8', 'binary')
crypted += cipher.final('binary');
return crypted;
}
private encryptPublic(key, publicKey) {
const messageDigest = forge.md.sha256.create();
messageDigest.update(key, 'utf8')
return publicKey.encrypt(messageDigest.digest().getBytes());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment