Last active
November 21, 2018 19:41
-
-
Save tgoldenberg/06378e9d6b16269f8c9ec609c88c0252 to your computer and use it in GitHub Desktop.
Proof of Concept for a KYC provider digital currency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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: '[email protected]' }, | |
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