From 1d0f01c133e90869b9388d0607c61b8cd116e254 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 14 Jul 2014 22:08:27 -0700 Subject: [PATCH] paypro: first pass at implementing payment protocol for x509. --- lib/PayPro.js | 37 ++++++++++++++++++++++++++++------ package.json | 5 +++-- test/data/x509.crt | 19 ++++++++++++++++++ test/data/x509.csr | 16 +++++++++++++++ test/data/x509.der | Bin 0 -> 778 bytes test/data/x509.key | 27 +++++++++++++++++++++++++ test/test.PayPro.js | 48 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 test/data/x509.crt create mode 100644 test/data/x509.csr create mode 100644 test/data/x509.der create mode 100644 test/data/x509.key diff --git a/lib/PayPro.js b/lib/PayPro.js index 17f8e3d..c948243 100644 --- a/lib/PayPro.js +++ b/lib/PayPro.js @@ -206,12 +206,25 @@ PayPro.prototype.sign = function(key) { var pki_type = this.get('pki_type'); - if (pki_type === 'SIN') + if (pki_type === 'SIN') { var sig = this.sinSign(key); - else + } else if (pki_type === 'none' + || pki_type === 'x509+sha1' + || pki_type === 'x509+sha256') { + var crypto = require('crypto'); + var pki_data = this.get('pki_data'); // contains one or more x509 certs + var details = this.get('serialized_payment_details'); + var signature = crypto.createSign('RSA-SHA256'); + var buf = this.serializeForSig(); + signature.update(buf); + var key = require('fs').readFileSync(__dirname + '/../test/data/x509.key'); + var sig = signature.sign(key); + } else { throw new Error('Unsupported pki_type'); - + } + this.set('signature', sig); + return this; }; @@ -221,10 +234,22 @@ PayPro.prototype.verify = function() { var pki_type = this.get('pki_type'); - if (pki_type === 'SIN') + if (pki_type === 'SIN') { return this.sinVerify(); - else - throw new Error('Unsupported pki_type'); + } else if (pki_type === 'none' + || pki_type === 'x509+sha1' + || pki_type === 'x509+sha256') { + var crypto = require('crypto'); + var sig = this.get('signature'); + var pki_data = this.get('pki_data'); // contains one or more x509 certs + var details = this.get('serialized_payment_details'); + var buf = this.serializeForSig(); + var verifier = crypto.createVerify('RSA-SHA256'); + verifier.update(buf); + return verifier.verify(buf, sig); + } + + throw new Error('Unsupported pki_type'); }; //default signing function for prototype.sign diff --git a/package.json b/package.json index df4fa21..17561b9 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "grunt-contrib-watch": "~0.5.3", "grunt-markdown": "~0.5.0", "grunt-mocha-test": "~0.8.2", - "grunt-shell": "~0.6.4", + "grunt-shell": "~0.6.4", "protobufjs": "=3.0.0", "coveralls": "^2.10.0", "istanbul": "~0.2.6", @@ -104,7 +104,8 @@ "./lib/Key.js": "./lib/browser/Key.js", "./lib/Point.js": "./lib/browser/Point.js", "./lib/ECIES.js": "./lib/browser/ECIES.js", - "./lib/SecureRandom.js": "./lib/browser/SecureRandom.js" + "./lib/SecureRandom.js": "./lib/browser/SecureRandom.js", + "./lib/PayPro.js": "./lib/browser/PayPro.js" }, "license": "MIT", "engines": { diff --git a/test/data/x509.crt b/test/data/x509.crt new file mode 100644 index 0000000..d2c04ad --- /dev/null +++ b/test/data/x509.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDBjCCAe4CCQDGf3j9NsTyjzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB +VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0 +cyBQdHkgTHRkMB4XDTE0MDcxNTAyMTUyM1oXDTE1MDcxNTAyMTUyM1owRTELMAkG +A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0 +IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +API4A1LJKeWHpbz8bY1rFCeJ3YXPXz6YQdaCF1m8cTQYWy3vw8COou8d0Zogizgp +eXpNIYhREu1dl5yuAYmgpEMGpNr8I6euMx08j3f9jS/vY3SwJbW9nw2lIdiGwAmi +qOtqWOru/2nL1KE7n0rjEFto5UNyHIyIhuLN+KNcg0X1Ch9hSxydTRjBFThzTHRV +Qqba9KELbO4WI3JWaBQsxyer84TJf9eO8dW9ea3BxNgGkKt6XwHiDyXc+nc4vhUa +5upm1z+2nX4UlaokJTPRvAHWD5Exc1X/LbuaCOwNexrCNbPcwBYYjltcfMULmPka +zStX8clZJJDsHM/uBr5vZjcCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAQrU2R1Yw +WJuqZnMqrk+EGIL6tAlyqj1W9j65N0jnPsvBVy3fWJ3AdSzQcJO8PzPavj1R4Nu9 +y55KZa6MZzAH7MkfPNZFoLUs4F7w0Sl+oHuMnw1HV4NeZBE653iQHx7Q+U8tJJKc +SnX0T5LXXPT9GuP/uzHlooKVNybcZ64ve89O8gw/GEidQdDOJ6RuWbdifADVInkP +dWQgsnMDGQmJGE7H77nZbrzMKZ2l0K44vEnxlxQiRqAOC3mDaSjaHfJmiGkfCjGZ +Pn7z8t051F8rXuzBHXUTqVtYd5kmeXN8BvGjF0g3QiQSF66CLm+bLEoRnyFEukfn +hDsMOVV628WjzA== +-----END CERTIFICATE----- diff --git a/test/data/x509.csr b/test/data/x509.csr new file mode 100644 index 0000000..3a0f255 --- /dev/null +++ b/test/data/x509.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx +ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAPI4A1LJKeWHpbz8bY1rFCeJ3YXPXz6YQdaCF1m8 +cTQYWy3vw8COou8d0ZogizgpeXpNIYhREu1dl5yuAYmgpEMGpNr8I6euMx08j3f9 +jS/vY3SwJbW9nw2lIdiGwAmiqOtqWOru/2nL1KE7n0rjEFto5UNyHIyIhuLN+KNc +g0X1Ch9hSxydTRjBFThzTHRVQqba9KELbO4WI3JWaBQsxyer84TJf9eO8dW9ea3B +xNgGkKt6XwHiDyXc+nc4vhUa5upm1z+2nX4UlaokJTPRvAHWD5Exc1X/LbuaCOwN +exrCNbPcwBYYjltcfMULmPkazStX8clZJJDsHM/uBr5vZjcCAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4IBAQBxeYIgZsLUfHYhAwLudGkd8G2pc6/GBZKHTWUaDmzhbKzg +8PeZARBpgpjv2kVVsSmPL4wr3jZyb6N8ttA6WZ5l6VdSqP87r4mFSsqWMaW4yurD +ueubsbuM/+31H5rR4+cBtskpnn1RUM06hRRcaZX6RgbWk5SfwP9YWa0KnL/eslqC +2DOZCG0miG0STGE0MOzGcOw9Ncxq1tsOPxkL+jVNFveLVipQPqVhKb1O1Zv09Odo +x3tjNA1QAmcWLpnB0fuBUoe3FCt4JV1iP4hKXdb/JGAfNeZOem3tCpUT+SHOcnVI ++TUA26j6O8HLaqWI7zpfaqUmFjfanKFPVJEWAFk5 +-----END CERTIFICATE REQUEST----- diff --git a/test/data/x509.der b/test/data/x509.der new file mode 100644 index 0000000000000000000000000000000000000000..e8a53eb98d8367d0d4aa77584f7acf28a567e968 GIT binary patch literal 778 zcmXqLVrDaFVtmKM$#AT`;;-3}PyGhGY@Awc9&O)w85vnw84O$vxeYkkm_u3Egqa*e z4TTK^K^zVquHgLKRNdf`#FA7)MFV+|AQz8>XI@EaQC@0^LU?9MdS*$nLO@BSf=@|` zft)z6p^1UHp{aq9p{bE^6p(9*#HE%sO^iy&9$;i;U~XdMX8`(Zl`k>QgCbI?i6 zr|nDk{K@Uj7E$lK+j>6UZieHvCh^EUg(ecwy6+Dk=v(w&_TnssZVS!IDqqEpK%uv> z)90*X>|C(KnQh6fKg!G38Oz%Am;de6f1g~kL3Qii`MgUNZ?qlYT(shKR>Z4!|1(ct zS!g}q>#;y|##84anVyceM`wR5j%jxN$|axZEi>0w;-IKSu}?{;)3RG%7INpj6H_h< z%Mj5yuD<$n%gOrdeIKvxtz3KX$PKm$tE=J}AMvZ+`BiSQPgLsJtF-I(+ve7ZOkJg- zYJ71I<2C+?hQ*=(b$8F=c*9#Qb;xw{odaSLebF&BN4aPGlsc;&{_$j_%7iyE=ijmI z%TF_BVrFDuL=GWf6azzuk-=%JnR}Q)#OzgR#aiq9TO^u(ZQ(3hWgGU*Zl}4&bGy?A z!*%aR%so)5bD?1J9(&_k`)mUr+}?Y7o>%I+o^%8DHz(z7uDLGQs`DW3!$r-y1=T(C zdELXC<5C2zo>xqem%H%OUsq+)9Iw(Z{*$i9eEBQ&`2TLhr;D1VnycMOU#DMv-tQBS zy@bbH#|!7wm*homPpVY|hlUCHpC@BU7HsaHd_|=TCPnuf%J|y*VgbD!ei}qI{-WWpNGL$Hn3v=1wX? e;_I69@@MOK3C>q^+2#Jc#hS-5wCeWJ#b*GIxiG*0 literal 0 HcmV?d00001 diff --git a/test/data/x509.key b/test/data/x509.key new file mode 100644 index 0000000..175ca6f --- /dev/null +++ b/test/data/x509.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA8jgDUskp5YelvPxtjWsUJ4ndhc9fPphB1oIXWbxxNBhbLe/D +wI6i7x3RmiCLOCl5ek0hiFES7V2XnK4BiaCkQwak2vwjp64zHTyPd/2NL+9jdLAl +tb2fDaUh2IbACaKo62pY6u7/acvUoTufSuMQW2jlQ3IcjIiG4s34o1yDRfUKH2FL +HJ1NGMEVOHNMdFVCptr0oQts7hYjclZoFCzHJ6vzhMl/147x1b15rcHE2AaQq3pf +AeIPJdz6dzi+FRrm6mbXP7adfhSVqiQlM9G8AdYPkTFzVf8tu5oI7A17GsI1s9zA +FhiOW1x8xQuY+RrNK1fxyVkkkOwcz+4Gvm9mNwIDAQABAoIBAQDgYO8DM4JyNDRe +W2CIzpa/AcGKAU3zyEvFEIHdCOm9HorohOFLcVaSN4dBRcBx6Em199mGU8Q6yqZ1 +5+NYwM0poe/5Q/Urkf2bqcwllWXC7/mr0Lk+IEhE9aHi2QDwbBQa8EsqZveH4+A2 +8+peDvXKF+O5lO3JaXe6hp87ham9lLGm1JD1uUz+wDwtc0FJh3rQsfUhCTMYxXA7 +ombGmbRbyZgHXOTXa6Q2KuKF+OpJETg6QpybGLzp8F6djfV7vCSNY5eeMQ2lPdtc +l05gdnExOtKwxjpoc5xAL1ScWMP0Oa4WUZtwTZT+xn37ZJezh4J9NDKdGWI0GjRz +MNFcOCCxAoGBAP+dhzJFpbaIrfqtzz2EGnCwFeupSdpJ53PSQZDho+ze//9UcD6n +n0NKaIdkEmaZZgBFaJbG1D07xeAaBKEMDboOiH4ccEcD+XjyxXdpiLTYrJeScvoU +iQuz52tyspwCl21kt8gwuEOFl4w5snxNH9u0CSDBtD2DcBEVEdhqLYl1AoGBAPKV +UvV8L/0UpQZ2b730zlI+6ClU3pM/qSl8QvHtb8RtIUyCXozPN+qmoGX74SzvDxJY +Ru9hYPUuPHpjfhixgSbqSg6cjfs7uaKDMFDNj/08Y/BTlN/dGjADhDXgujpqv/ZD +dPHQ2DhdNKN80rgPJ021hOj1cdCsF6RpyHyA7o97AoGAOLDwVib6PMSNiYZY6zTM +RGfZRL30AjTX32knX4GbwKIotrE8f7jfaqYrDrQUHKsy4yaBrscENVx3Y1+B3VH2 +DWjBvu6BvE5WWwvE3doLFsjjZm51j59UUcMhtUPn9w/gE8P9uqmLhHYxiUkWm9jj +EvAYAirT1by78x3wKkZKOS0CgYARLMFS4BgFsxB8BKakrFBvQkTtqDSZ+EfhyAp1 +VnozTgathA1tqr4qvuFcVxj6NXK7ucRL7nkO4tclUyX6WZbrSmsz3aGvx+q8ts0U +63jmVQA+Y6yGrQDNpXIW3nJQ8H3m0Z/V/xNP6klvycahgXEm71MZq0cDnyuNWG/5 +YKeDQQKBgGTtNsOKl3A4z/nlrSEBHl/8n76kOVeRNbbbvaFvfbLD9twsmcbZk8o5 +xHo9MJ/kAAJfCavXc/uhJsVl1TLN56pgjbnXqQSGB7rWpAtD08UTWaTLc7yyKRPq +70FEbd6tgfsu7zdGX69rPrNLcu+QFniytNwwu63qXp48LakIgeqq +-----END RSA PRIVATE KEY----- diff --git a/test/test.PayPro.js b/test/test.PayPro.js index d8dcf31..fb66c70 100644 --- a/test/test.PayPro.js +++ b/test/test.PayPro.js @@ -4,6 +4,7 @@ var chai = chai || require('chai'); var should = chai.should(); var expect = chai.expect; var bitcore = bitcore || require('../bitcore'); +var fs = require('fs'); var PayPro = bitcore.PayPro; var Key = bitcore.Key; @@ -319,4 +320,51 @@ describe('PayPro', function() { }); + var x509sig = new Buffer(0); + var x509path = __dirname + '/data/x509.der'; + var x509cert = fs.readFileSync(x509path); + + describe('#x509Sign', function() { + it('should sign assuming pki_type is x509', function() { + var pd = new PayPro.PaymentDetails(); + pd.set('time', 0); + var pdbuf = pd.toBuffer(); + var paypro = new PayPro(); + paypro.makePaymentRequest(); + paypro.set('serialized_payment_details', pdbuf); + paypro.set('pki_type', 'x509+sha256'); + + paypro.set('pki_data', x509cert); // contains one or more x509 certs + + var key = new bitcore.Key(); + key.private = bitcore.util.sha256('test key'); + key.regenerateSync(); + var sig = paypro.get('signature'); + x509sig = sig; + sig.length.should.be.greaterThan(0); + }); + }); + + describe('#x509Verify', function() { + it('should verify assuming pki_type is x509', function() { + var pd = new PayPro.PaymentDetails(); + pd.set('time', 0); + var pdbuf = pd.toBuffer(); + var paypro = new PayPro(); + paypro.makePaymentRequest(); + paypro.set('serialized_payment_details', pdbuf); + paypro.set('pki_type', 'x509+sha256'); + + paypro.set('signature', x509sig); // sig buffer + paypro.set('pki_data', x509cert); // contains one or more x509 certs + + var key = new bitcore.Key(); + key.private = bitcore.util.sha256('test key'); + key.regenerateSync(); + paypro.sign(key); + var verify = paypro.verify(); + verify.should.equal(true); + }); + + }); });