Skip to content

Instantly share code, notes, and snippets.

@tgoldenberg
Last active November 21, 2018 19:41
Show Gist options
  • Save tgoldenberg/06378e9d6b16269f8c9ec609c88c0252 to your computer and use it in GitHub Desktop.
Save tgoldenberg/06378e9d6b16269f8c9ec609c88c0252 to your computer and use it in GitHub Desktop.
Proof of Concept for a KYC provider digital currency
/**
* Proof of concept for a KYC-enabled digital currency
* In short, a user submits their information to a KYC provider (Oracle) along with proof of identity (similar to Jumio, etc.)
* KYC provider provides signature for the user's identity.
*
* The user can then share pieces of the identity with the relevant
* signature for transactions. This logic can even be part of the transaction validation logic of the digital currency.
* What follows is just a simple example that can be run via NodeJS.
*/
/* libraries for cryptography */
const RIPEMD160 = require('ripemd160');
const EC = require('elliptic').ec;
const sha256 = require('js-sha256');
/* starting parameters */
const TEST_MSG = 'I want to send this money'; // This would normally be the transaction hash with amount of money, publicScriptKey
const USER_PUBLIC_KEY = '040c1fbe8b870d636823963ff21ba6e5250571848714203a08ae8700e0d97a1d7bb94ae888af72ac9a4fe02d558599d27c8986398902fa9ac0c1654f5839db1af5';
const USER_PRIVATE_KEY = '2ec6d2808dc7b9d11e49516cfc747435feae8e9872d63c92bc5bde68a894199f';
const KYC_PROVIDER_PUBLIC_KEY = '049a6f8905311fa8162d2f0b5eac6b022d1d8f2ab53bb286b7f14ddf88c1ec23a4490eacdf8819d9607981c59118a52e06941a96c5464be51089b7f87c5db883ab';
const KYC_PROVIDER_PRIVATE_KEY = 'e217c92db3d36acda558a80cc958dc3f12d2bf8bc1e7d719383f466c69114a89';
const ec = new EC('secp256k1'); // initializing the ECDSA algorithm for digital signature (a la Bitcoin)
/* user submits information to KYC provider */
const userData = {
firstname: { label: "First Name", value: 'John' },
lastname: { label: "Last Name", value: 'Doe' },
address_line_1: { label: "Address Line 1", value: '123 Sesame Street' },
address_line_2: { label: "Address Line 2", value: '' },
city: { label: "City", value: 'New York City' },
state: { label: "State", value: 'NY' },
zipcode: { label: "Zipcode", value: '10001' },
country: { label: "Country", value: 'US' },
mobile: { label: "Mobile", value: '555-555-5555' },
ssn: { label: "Ssn", value: '555-55-5555' },
dob: { label: "Dob", value: '01-01-1970' },
citizenship_country: { label: "Citizenship country", value: 'US' },
email: { label: "email", value: 'tom@example.com' },
ofac: { label: "OFAC list", value: false },
watchlists: { label: "Watchlists", value: false }
};
/**
* Information is collected via online form and sent to a KYC provider
* - KYC providers function as an Oracle with a public/private key pair
* - KYC providers must be approved by the community and any governing member can vote against a particular vendor
*
* KYC provider checks information via drivers' license, passport, selfie, email verification, SMS verification, etc.
* - KYC provider verifies information and checks against OFAC lists, watchlists, etc.
* - KYC provider uses private key to create signature for each data field
*/
let response = { };
for (let key in userData) {
let message = sha256(JSON.stringify(userData[key]));
let signature = createSignature(message, KYC_PROVIDER_PRIVATE_KEY);
response[key] = {
signature: signature.toDER('hex'),
timestamp: Date.now()
}
}
response['to'] = USER_PUBLIC_KEY;
response['from'] = KYC_PROVIDER_PUBLIC_KEY;
response['from_signature'] = createSignature(sha256(JSON.stringify(response)), KYC_PROVIDER_PRIVATE_KEY).toDER('hex');
// console.log('> Response: \n\n\n', JSON.stringify(response));
/*
* The KYC provider maintains the customer information as a record for compliance purposes
* Now the user wants to receive money from someone but needs to verify that he or she is from
* the US and is not on any OFAC watchlists.
*/
let data = {
citizenship_country: { label: "Citizenship Country", value: 'US' },
signature: '30450220693ab843fd432bf197e17fab6ab35f75f4315afeb22314b6c9f380dd7cb23d71022100f85c7317250f69f044f18768d0475cdecb4642f0cfdb5149da5c6017d56dbe98',
kyc_public_key: KYC_PROVIDER_PUBLIC_KEY
}
console.log('> Verified citizenship country: ', checkData(data));
function checkData(data) {
let message = sha256(JSON.stringify(data.citizenship_country));
let isVerified = verifySignature(message, KYC_PROVIDER_PUBLIC_KEY, data.signature);
return isVerified;
}
/* hash message - this method hashes the transaction header with SHA256 and then with RIPEMD160 */
function Hash(msg) {
let result = sha256(msg);
return new RIPEMD160().update(msg).digest('hex');
}
function createSignature(message, privateKey) {
const messageHash = Hash(message);
const privateKeyPair = ec.keyFromPrivate(privateKey);
const signature = ec.sign(messageHash, privateKeyPair); // generate a signature on the hashed message with the private key
return signature;
}
function verifySignature(message, publicAddress, signature) {
const messageHash = Hash(message);
const publicKeyPair = ec.keyFromPublic(publicAddress, 'hex'); // use the accessible public key to verify the signature
const isVerified = publicKeyPair.verify(messageHash, signature);
return isVerified;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment