const bigInt = require("big-integer"); // Consts for P256 curve. Adjust accordingly const two = new bigInt(2), // 115792089210356248762697446949407573530086143415290314195533631308867097853951 prime = two.pow(256).subtract( two.pow(224) ).add( two.pow(192) ).add( two.pow(96) ).subtract(1), b = new bigInt( '41058363725152142129326129780047268409114441015993725554835256314039467401291' ), // Pre-computed value, or literal // 28948022302589062190674361737351893382521535853822578548883407827216774463488 pIdent = prime.add(1).divide(4); function pad_with_zeroes(number, length) { var retval = '' + number; while (retval.length < length) { retval = '0' + retval; } return retval; } /** * Point decompress NIST curve * @param {string} Compressed representation in hex string * @return {string} Uncompressed representation in hex string */ function ECPointDecompress( comp ) { var signY = new Number(comp[1]) - 2; var x = new bigInt(comp.substring(2), 16); // y^2 = x^3 - 3x + b var y = x.pow(3).subtract( x.multiply(3) ).add( b ).modPow( pIdent, prime ); // If the parity doesn't match it's the *other* root if( y.mod(2).toJSNumber() !== signY ) { // y = prime - y y = prime.subtract( y ); } return '04' + pad_with_zeroes(x.toString(16), 64) + pad_with_zeroes(y.toString(16), 64); } console.log(ECPointDecompress('035d77c1e3eac37f685aeea2ae872c4e7e4d159756e57601db3bcccbc549f360b2'))