Skip to content

Repository files navigation

Forge

npm package

Build status

A native implementation of TLS (and various other cryptographic tools) in JavaScript.

Introduction

The Forge software is a fully native implementation of the TLS protocol in JavaScript as well as a set of tools for developing Web Apps that utilize many network resources.

Performance

Forge is fast. Benchmarks against other popular JavaScript cryptography libraries can be found here:

http://dominictarr.github.io/crypto-bench/

http://cryptojs.altervista.org/test/simulate-threading-speed_test.html

Getting Started


Node.js

If you want to use forge with node.js, it is available through npm:

https://npmjs.org/package/node-forge

Installation:

npm install node-forge

You can then use forge as a regular module:

var forge = require('node-forge');

Requirements

  • General
    • Optional: GNU autotools for the build infrastructure if using Flash.
  • Building a Browser Bundle:
    • nodejs
    • npm
  • Testing
  • Optional: Flash

Building a browser bundle

To create a minimized JavaScript bundle, run the following:

npm install
npm run minify

This will create a single minimized file that can be included in the browser:

js/forge.min.js

Include the file via:

<scriptsrc="js/forge.min.js"></script>

Note that the minify script depends on the requirejs package, and that the requirejs binary 'r.js' assumes that the name of the node binary is 'node' not 'nodejs', as it is on some systems. You may need to change the hashbang line to use 'nodejs' or run the command manually.

To create a single non-minimized file that can be included in the browser:

npm install
npm run bundle

This will create:

js/forge.bundle.js

Include the file via:

<scriptsrc="js/forge.bundle.js"></script>

The above bundles will synchronously create a global 'forge' object.

Keep in mind that these bundles will not include any WebWorker scripts (eg: prime.worker.js) or their dependencies, so these will need to be accessible from the browser if any WebWorkers are used.

Testing with NodeJS & RequireJS

A test server for node.js can be found at ./nodejs. The following are included:

  • Example of how to use forge within NodeJS in the form of a mocha test.
  • Example of how to serve forge to the browser using RequireJS.

To run:

cd nodejs
npm install
npm test
npm start

Old build system that includes flash support

To build the whole project, including Flash, run the following:

$ ./build-setup
$ make

This will create the SWF, symlink all the JavaScript files, and build a Python SSL module for testing. To see configure options, run ./configure --help.

Old test system including flash support

A test server is provided which can be run in TLS mode and non-TLS mode. Use the --help option to get help for configuring ports. The server will print out the local URL you can vist to run tests.

Some of the simplier tests should be run with just the non-TLS server::

$ ./tests/server.py

More advanced tests need TLS enabled::

$ ./tests/server.py --tls

Contributing


Any contributions (eg: PRs) that are accepted will be brought under the same license used by the rest of the Forge project. This license allows Forge to be used under the terms of either the BSD License or the GNU General Public License (GPL) Version 2.

See: LICENSE

If a contribution contains 3rd party source code with its own license, it may retain it, so long as that license is compatible with the Forge license.

Documentation


Transports

Ciphers

PKI

Message Digests

Utilities


If at any time you wish to disable the use of native code, where available, for particular forge features like its secure random number generator, you may set the disableNativeCode flag on forge to true. It is not recommended that you set this flag as native code is typically more performant and may have stronger security properties. It may be useful to set this flag to test certain features that you plan to run in environments that are different from your testing environment.

To disable native code when including forge in the browser:

forge={disableNativeCode: true};// now include forge script file(s)// Note: with this approach, script files *must*// be included after initializing the global forge var// alternatively, include script files first and then callforge=forge({disableNativeCode: true});// Note: forge will be permanently reconfigured now;// to avoid this but use the same "forge" var name,// you can wrap your code in a function to shadow the// global var, eg:(function(forge){// ...})(forge({disableNativeCode: true}));

To disable native code when using node.js:

varforge=require('node-forge')({disableNativeCode: true});

Transports

### TLS

Provides a native javascript client and server-side TLS implementation.

Examples

// create TLS clientvarclient=forge.tls.createConnection({server: false,caStore: /* Array of PEM-formatted certs or a CA store object */,sessionCache: {},// supported cipher suites in order of preferencecipherSuites: [forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],virtualHost: 'example.com',verify: function(connection,verified,depth,certs){if(depth===0){varcn=certs[0].subject.getField('CN').value;if(cn!=='example.com'){verified={alert: forge.tls.Alert.Description.bad_certificate,message: 'Certificate common name does not match hostname.'};}}returnverified;},connected: function(connection){console.log('connected');// send message to serverconnection.prepare(forge.util.encodeUtf8('Hi server!'));/* NOTE: experimental, start heartbeat retransmission timer myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000);*/},/* provide a client-side cert if you want getCertificate: function(connection, hint) { return myClientCertificate; }, /* the private key for the client-side cert if provided */getPrivateKey: function(connection,cert){returnmyClientPrivateKey;},tlsDataReady: function(connection){// TLS data (encrypted) is ready to be sent to the serversendToServerSomehow(connection.tlsData.getBytes());// if you were communicating with the server below, you'd do:// server.process(connection.tlsData.getBytes());},dataReady: function(connection){// clear data from the server is readyconsole.log('the server sent: '+forge.util.decodeUtf8(connection.data.getBytes()));// close connectionconnection.close();},/* NOTE: experimental heartbeatReceived: function(connection, payload) { // restart retransmission timer, look at payload clearInterval(myHeartbeatTimer); myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000); payload.getBytes(); },*/closed: function(connection){console.log('disconnected');},error: function(connection,error){console.log('uh oh',error);}});// start the handshake processclient.handshake();// when encrypted TLS data is received from the server, process itclient.process(encryptedBytesFromServer);// create TLS servervarserver=forge.tls.createConnection({server: true,caStore: /* Array of PEM-formatted certs or a CA store object */,sessionCache: {},// supported cipher suites in order of preferencecipherSuites: [forge.tls.CipherSuites.TLS_RSA_WITH_AES_128_CBC_SHA,forge.tls.CipherSuites.TLS_RSA_WITH_AES_256_CBC_SHA],// require a client-side certificate if you wantverifyClient: true,verify: function(connection,verified,depth,certs){if(depth===0){varcn=certs[0].subject.getField('CN').value;if(cn!=='the-client'){verified={alert: forge.tls.Alert.Description.bad_certificate,message: 'Certificate common name does not match expected client.'};}}returnverified;},connected: function(connection){console.log('connected');// send message to clientconnection.prepare(forge.util.encodeUtf8('Hi client!'));/* NOTE: experimental, start heartbeat retransmission timer myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000);*/},getCertificate: function(connection,hint){returnmyServerCertificate;},getPrivateKey: function(connection,cert){returnmyServerPrivateKey;},tlsDataReady: function(connection){// TLS data (encrypted) is ready to be sent to the clientsendToClientSomehow(connection.tlsData.getBytes());// if you were communicating with the client above you'd do:// client.process(connection.tlsData.getBytes());},dataReady: function(connection){// clear data from the client is readyconsole.log('the client sent: '+forge.util.decodeUtf8(connection.data.getBytes()));// close connectionconnection.close();},/* NOTE: experimental heartbeatReceived: function(connection, payload) { // restart retransmission timer, look at payload clearInterval(myHeartbeatTimer); myHeartbeatTimer = setInterval(function() { connection.prepareHeartbeatRequest(forge.util.createBuffer('1234')); }, 5*60*1000); payload.getBytes(); },*/closed: function(connection){console.log('disconnected');},error: function(connection,error){console.log('uh oh',error);}});// when encrypted TLS data is received from the client, process itserver.process(encryptedBytesFromClient);

Connect to a TLS server using node's net.Socket:

varsocket=newnet.Socket();varclient=forge.tls.createConnection({server: false,verify: function(connection,verified,depth,certs){// skip verification for testingconsole.log('[tls] server certificate verified');returntrue;},connected: function(connection){console.log('[tls] connected');// prepare some data to send (note that the string is interpreted as// 'binary' encoded, which works for HTTP which only uses ASCII, use// forge.util.encodeUtf8(str) otherwiseclient.prepare('GET / HTTP/1.0\r\n\r\n');},tlsDataReady: function(connection){// encrypted data is ready to be sent to the servervardata=connection.tlsData.getBytes();socket.write(data,'binary');// encoding should be 'binary'},dataReady: function(connection){// clear data from the server is readyvardata=connection.data.getBytes();console.log('[tls] data received from the server: '+data);},closed: function(){console.log('[tls] disconnected');},error: function(connection,error){console.log('[tls] error',error);}});socket.on('connect',function(){console.log('[socket] connected');client.handshake();});socket.on('data',function(data){client.process(data.toString('binary'));// encoding should be 'binary'});socket.on('end',function(){console.log('[socket] disconnected');});// connect to google.comsocket.connect(443,'google.com');// or connect to gmail's imap server (but don't send the HTTP header above)//socket.connect(993, 'imap.gmail.com');
### HTTP

Provides a native JavaScript mini-implementation of an http client that uses pooled sockets.

Examples

// create an HTTP GET requestvarrequest=forge.http.createRequest({method: 'GET',path: url.path});// send the request somewheresendSomehow(request.toString());// receive responsevarbuffer=forge.util.createBuffer();varresponse=forge.http.createResponse();varsomeAsyncDataHandler=function(bytes){if(!response.bodyReceived){buffer.putBytes(bytes);if(!response.headerReceived){if(response.readHeader(buffer)){console.log('HTTP response header: '+response.toString());}}if(response.headerReceived&&!response.bodyReceived){if(response.readBody(buffer)){console.log('HTTP response body: '+response.body);}}}};
### SSH

Provides some SSH utility functions.

Examples

// encodes (and optionally encrypts) a private RSA key as a Putty PPK fileforge.ssh.privateKeyToPutty(privateKey,passphrase,comment);// encodes a public RSA key as an OpenSSH fileforge.ssh.publicKeyToOpenSSH(key,comment);// encodes a private RSA key as an OpenSSH fileforge.ssh.privateKeyToOpenSSH(privateKey,passphrase);// gets the SSH public key fingerprint in a byte bufferforge.ssh.getPublicKeyFingerprint(key);// gets a hex-encoded, colon-delimited SSH public key fingerprintforge.ssh.getPublicKeyFingerprint(key,{encoding: 'hex',delimiter: ':'});
### XHR

Provides an XmlHttpRequest implementation using forge.http as a backend.

Examples

### Sockets

Provides an interface to create and use raw sockets provided via Flash.

Examples


### CIPHER

Provides a basic API for block encryption and decryption. There is built-in support for the ciphers: AES, 3DES, and DES, and for the modes of operation: ECB, CBC, CFB, OFB, CTR, and GCM.

These algorithms are currently supported:

  • AES-ECB
  • AES-CBC
  • AES-CFB
  • AES-OFB
  • AES-CTR
  • AES-GCM
  • 3DES-ECB
  • 3DES-CBC
  • DES-ECB
  • DES-CBC

When using an AES algorithm, the key size will determine whether AES-128, AES-192, or AES-256 is used (all are supported). When a DES algorithm is used, the key size will determine whether 3DES or regular DES is used. Use a 3DES algorithm to enforce Triple-DES.

Examples

// generate a random key and IV// Note: a key size of 16 bytes will use AES-128, 24 => AES-192, 32 => AES-256varkey=forge.random.getBytesSync(16);variv=forge.random.getBytesSync(16);/* alternatively, generate a password-based 16-byte keyvar salt = forge.random.getBytesSync(128);var key = forge.pkcs5.pbkdf2('password', salt, numIterations, 16);*/// encrypt some bytes using CBC mode// (other modes include: ECB, CFB, OFB, CTR, and GCM)varcipher=forge.cipher.createCipher('AES-CBC',key);cipher.start({iv: iv});cipher.update(forge.util.createBuffer(someBytes));cipher.finish();varencrypted=cipher.output;// outputs encrypted hexconsole.log(encrypted.toHex());// decrypt some bytes using CBC mode// (other modes include: CFB, OFB, CTR, and GCM)vardecipher=forge.cipher.createDecipher('AES-CBC',key);decipher.start({iv: iv});decipher.update(encrypted);decipher.finish();// outputs decrypted hexconsole.log(decipher.output.toHex());// encrypt some bytes using GCM modevarcipher=forge.cipher.createCipher('AES-GCM',key);cipher.start({iv: iv,// should be a 12-byte binary-encoded string or byte bufferadditionalData: 'binary-encoded string',// optionaltagLength: 128// optional, defaults to 128 bits});cipher.update(forge.util.createBuffer(someBytes));cipher.finish();varencrypted=cipher.output;vartag=cipher.mode.tag;// outputs encrypted hexconsole.log(encrypted.toHex());// outputs authentication tagconsole.log(tag.toHex());// decrypt some bytes using GCM modevardecipher=forge.cipher.createDecipher('AES-GCM',key);decipher.start({iv: iv,additionalData: 'binary-encoded string',// optionaltagLength: 128,// optional, defaults to 128 bitstag: tag// authentication tag from encryption});decipher.update(encrypted);varpass=decipher.finish();// pass is false if there was a failure (eg: authentication tag didn't match)if(pass){// outputs decrypted hexconsole.log(decipher.output.toHex());}

Using forge in node.js to match openssl's "enc" command line tool (Note: OpenSSL "enc" uses a non-standard file format with a custom key derivation function and a fixed iteration count of 1, which some consider less secure than alternatives such as OpenPGP/GnuPG):

varforge=require('node-forge');varfs=require('fs');// openssl enc -des3 -in input.txt -out input.encfunctionencrypt(password){varinput=fs.readFileSync('input.txt',{encoding: 'binary'});// 3DES key and IV sizesvarkeySize=24;varivSize=8;// get derived bytes// Notes:// 1. If using an alternative hash (eg: "-md sha1") pass// "forge.md.sha1.create()" as the final parameter.// 2. If using "-nosalt", set salt to null.varsalt=forge.random.getBytesSync(8);// var md = forge.md.sha1.create(); // "-md sha1"varderivedBytes=forge.pbe.opensslDeriveBytes(password,salt,keySize+ivSize/*, md*/);varbuffer=forge.util.createBuffer(derivedBytes);varkey=buffer.getBytes(keySize);variv=buffer.getBytes(ivSize);varcipher=forge.cipher.createCipher('3DES-CBC',key);cipher.start({iv: iv});cipher.update(forge.util.createBuffer(input,'binary'));cipher.finish();varoutput=forge.util.createBuffer();// if using a salt, prepend this to the output:if(salt!==null){output.putBytes('Salted__');// (add to match openssl tool output)output.putBytes(salt);}output.putBuffer(cipher.output);fs.writeFileSync('input.enc',output.getBytes(),{encoding: 'binary'});}// openssl enc -d -des3 -in input.enc -out input.dec.txtfunctiondecrypt(password){varinput=fs.readFileSync('input.enc',{encoding: 'binary'});// parse salt from inputinput=forge.util.createBuffer(input,'binary');// skip "Salted__" (if known to be present)input.getBytes('Salted__'.length);// read 8-byte saltvarsalt=input.getBytes(8);// Note: if using "-nosalt", skip above parsing and use// var salt = null;// 3DES key and IV sizesvarkeySize=24;varivSize=8;varderivedBytes=forge.pbe.opensslDeriveBytes(password,salt,keySize+ivSize);varbuffer=forge.util.createBuffer(derivedBytes);varkey=buffer.getBytes(keySize);variv=buffer.getBytes(ivSize);vardecipher=forge.cipher.createDecipher('3DES-CBC',key);decipher.start({iv: iv});decipher.update(input);varresult=decipher.finish();// check 'result' for true/falsefs.writeFileSync('input.dec.txt',decipher.output.getBytes(),{encoding: 'binary'});}
### AES

Provides AES encryption and decryption in CBC, CFB, OFB, CTR, and GCM modes. See CIPHER for examples.

### DES

Provides 3DES and DES encryption and decryption in ECB and CBC modes. See CIPHER for examples.

### RC2

Examples

// generate a random key and IVvarkey=forge.random.getBytesSync(16);variv=forge.random.getBytesSync(8);// encrypt some bytesvarcipher=forge.rc2.createEncryptionCipher(key);cipher.start(iv);cipher.update(forge.util.createBuffer(someBytes));cipher.finish();varencrypted=cipher.output;// outputs encrypted hexconsole.log(encrypted.toHex());// decrypt some bytesvarcipher=forge.rc2.createDecryptionCipher(key);cipher.start(iv);cipher.update(encrypted);cipher.finish();// outputs decrypted hexconsole.log(cipher.output.toHex());

Provides X.509 certificate and RSA public and private key encoding, decoding, encryption/decryption, and signing/verifying.

### RSA

Examples

varrsa=forge.pki.rsa;// generate an RSA key pair synchronouslyvarkeypair=rsa.generateKeyPair({bits: 2048,e: 0x10001});// generate an RSA key pair asynchronously (uses web workers if available)// use workers: -1 to run a fast core estimator to optimize # of workersrsa.generateKeyPair({bits: 2048,workers: 2},function(err,keypair){// keypair.privateKey, keypair.publicKey});// generate an RSA key pair in steps that attempt to run for a specified period// of time on the main JS threadvarstate=rsa.createKeyPairGenerationState(2048,0x10001);varstep=function(){// run for 100 msif(!rsa.stepKeyPairGenerationState(state,100)){setTimeout(step,1);}else{// done, turn off progress indicator, use state.keys}};// turn on progress indicator, schedule generation to runsetTimeout(step);// sign data with a private key and output DigestInfo DER-encoded bytes// (defaults to RSASSA PKCS#1 v1.5)varmd=forge.md.sha1.create();md.update('sign this','utf8');varsignature=privateKey.sign(md);// verify data with a public key// (defaults to RSASSA PKCS#1 v1.5)varverified=publicKey.verify(md.digest().bytes(),signature);// sign data using RSASSA-PSS where PSS uses a SHA-1 hash, a SHA-1 based// masking function MGF1, and a 20 byte saltvarmd=forge.md.sha1.create();md.update('sign this','utf8');varpss=forge.pss.create({md: forge.md.sha1.create(),mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),saltLength: 20// optionally pass 'prng' with a custom PRNG implementation// optionalls pass 'salt' with a forge.util.ByteBuffer w/custom salt});varsignature=privateKey.sign(md,pss);// verify RSASSA-PSS signaturevarpss=forge.pss.create({md: forge.md.sha1.create(),mgf: forge.mgf.mgf1.create(forge.md.sha1.create()),saltLength: 20// optionally pass 'prng' with a custom PRNG implementation});varmd=forge.md.sha1.create();md.update('sign this','utf8');publicKey.verify(md.digest().getBytes(),signature,pss);// encrypt data with a public key (defaults to RSAES PKCS#1 v1.5)varencrypted=publicKey.encrypt(bytes);// decrypt data with a private key (defaults to RSAES PKCS#1 v1.5)vardecrypted=privateKey.decrypt(encrypted);// encrypt data with a public key using RSAES PKCS#1 v1.5varencrypted=publicKey.encrypt(bytes,'RSAES-PKCS1-V1_5');// decrypt data with a private key using RSAES PKCS#1 v1.5vardecrypted=privateKey.decrypt(encrypted,'RSAES-PKCS1-V1_5');// encrypt data with a public key using RSAES-OAEPvarencrypted=publicKey.encrypt(bytes,'RSA-OAEP');// decrypt data with a private key using RSAES-OAEPvardecrypted=privateKey.decrypt(encrypted,'RSA-OAEP');// encrypt data with a public key using RSAES-OAEP/SHA-256varencrypted=publicKey.encrypt(bytes,'RSA-OAEP',{md: forge.md.sha256.create()});// decrypt data with a private key using RSAES-OAEP/SHA-256vardecrypted=privateKey.decrypt(encrypted,'RSA-OAEP',{md: forge.md.sha256.create()});// encrypt data with a public key using RSAES-OAEP/SHA-256/MGF1-SHA-1// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Paddingvarencrypted=publicKey.encrypt(bytes,'RSA-OAEP',{md: forge.md.sha256.create(),mgf1: {md: forge.md.sha1.create()}});// decrypt data with a private key using RSAES-OAEP/SHA-256/MGF1-SHA-1// compatible with Java's RSA/ECB/OAEPWithSHA-256AndMGF1Paddingvardecrypted=privateKey.decrypt(encrypted,'RSA-OAEP',{md: forge.md.sha256.create(),mgf1: {md: forge.md.sha1.create()}});
### RSA-KEM

Examples

// generate an RSA key pair asynchronously (uses web workers if available)// use workers: -1 to run a fast core estimator to optimize # of workersforge.rsa.generateKeyPair({bits: 2048,workers: -1},function(err,keypair){// keypair.privateKey, keypair.publicKey});// generate and encapsulate a 16-byte secret keyvarkdf1=newforge.kem.kdf1(forge.md.sha1.create());varkem=forge.kem.rsa.create(kdf1);varresult=kem.encrypt(keypair.publicKey,16);// result has 'encapsulation' and 'key'// encrypt some bytesvariv=forge.random.getBytesSync(12);varsomeBytes='hello world!';varcipher=forge.cipher.createCipher('AES-GCM',result.key);cipher.start({iv: iv});cipher.update(forge.util.createBuffer(someBytes));cipher.finish();varencrypted=cipher.output.getBytes();vartag=cipher.mode.tag.getBytes();// send 'encrypted', 'iv', 'tag', and result.encapsulation to recipient// decrypt encapsulated 16-byte secret keyvarkdf1=newforge.kem.kdf1(forge.md.sha1.create());varkem=forge.kem.rsa.create(kdf1);varkey=kem.decrypt(keypair.privateKey,result.encapsulation,16);// decrypt some bytesvardecipher=forge.cipher.createDecipher('AES-GCM',key);decipher.start({iv: iv,tag: tag});decipher.update(forge.util.createBuffer(encrypted));varpass=decipher.finish();// pass is false if there was a failure (eg: authentication tag didn't match)if(pass){// outputs 'hello world!'console.log(decipher.output.getBytes());}
### X.509

Examples

varpki=forge.pki;// convert a PEM-formatted public key to a Forge public keyvarpublicKey=pki.publicKeyFromPem(pem);// convert a Forge public key to PEM-formatvarpem=pki.publicKeyToPem(publicKey);// convert an ASN.1 SubjectPublicKeyInfo to a Forge public keyvarpublicKey=pki.publicKeyFromAsn1(subjectPublicKeyInfo);// convert a Forge public key to an ASN.1 SubjectPublicKeyInfovarsubjectPublicKeyInfo=pki.publicKeyToAsn1(publicKey);// gets a SHA-1 RSAPublicKey fingerprint a byte bufferpki.getPublicKeyFingerprint(key);// gets a SHA-1 SubjectPublicKeyInfo fingerprint a byte bufferpki.getPublicKeyFingerprint(key,{type: 'SubjectPublicKeyInfo'});// gets a hex-encoded, colon-delimited SHA-1 RSAPublicKey public key fingerprintpki.getPublicKeyFingerprint(key,{encoding: 'hex',delimiter: ':'});// gets a hex-encoded, colon-delimited SHA-1 SubjectPublicKeyInfo public key fingerprintpki.getPublicKeyFingerprint(key,{type: 'SubjectPublicKeyInfo',encoding: 'hex',delimiter: ':'});// gets a hex-encoded, colon-delimited MD5 RSAPublicKey public key fingerprintpki.getPublicKeyFingerprint(key,{md: forge.md.md5.create(),encoding: 'hex',delimiter: ':'});// creates a CA storevarcaStore=pki.createCaStore([/* PEM-encoded cert */, ...]);// add a certificate to the CA storecaStore.addCertificate(certObjectOrPemString);// gets the issuer (its certificate) for the given certificatevarissuerCert=caStore.getIssuer(subjectCert);// verifies a certificate chain against a CA storepki.verifyCertificateChain(caStore,chain,customVerifyCallback);// signs a certificate using the given private keycert.sign(privateKey);// signs a certificate using SHA-256 instead of SHA-1cert.sign(privateKey,forge.md.sha256.create());// verifies an issued certificate using the certificates public keyvarverified=issuer.verify(issued);// generate a keypair and create an X.509v3 certificatevarkeys=pki.rsa.generateKeyPair(2048);varcert=pki.createCertificate();cert.publicKey=keys.publicKey;// alternatively set public key from a csr//cert.publicKey = csr.publicKey;cert.serialNumber='01';cert.validity.notBefore=newDate();cert.validity.notAfter=newDate();cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear()+1);varattrs=[{name: 'commonName',value: 'example.org'},{name: 'countryName',value: 'US'},{shortName: 'ST',value: 'Virginia'},{name: 'localityName',value: 'Blacksburg'},{name: 'organizationName',value: 'Test'},{shortName: 'OU',value: 'Test'}];cert.setSubject(attrs);// alternatively set subject from a csr//cert.setSubject(csr.subject.attributes);cert.setIssuer(attrs);cert.setExtensions([{name: 'basicConstraints',cA: true},{name: 'keyUsage',keyCertSign: true,digitalSignature: true,nonRepudiation: true,keyEncipherment: true,dataEncipherment: true},{name: 'extKeyUsage',serverAuth: true,clientAuth: true,codeSigning: true,emailProtection: true,timeStamping: true},{name: 'nsCertType',client: true,server: true,email: true,objsign: true,sslCA: true,emailCA: true,objCA: true},{name: 'subjectAltName',altNames: [{type: 6,// URIvalue: 'http://example.org/webid#me'},{type: 7,// IPip: '127.0.0.1'}]},{name: 'subjectKeyIdentifier'}]);/* alternatively set extensions from a csrvar extensions = csr.getAttribute({name: 'extensionRequest'}).extensions;// optionally add more extensionsextensions.push.apply(extensions, [{ name: 'basicConstraints', cA: true}, { name: 'keyUsage', keyCertSign: true, digitalSignature: true, nonRepudiation: true, keyEncipherment: true, dataEncipherment: true}]);cert.setExtensions(extensions);*/// self-sign certificatecert.sign(keys.privateKey);// convert a Forge certificate to PEMvarpem=pki.certificateToPem(cert);// convert a Forge certificate from PEMvarcert=pki.certificateFromPem(pem);// convert an ASN.1 X.509x3 object to a Forge certificatevarcert=pki.certificateFromAsn1(obj);// convert a Forge certificate to an ASN.1 X.509v3 objectvarasn1Cert=pki.certificateToAsn1(cert);
### PKCS#5

Provides the password-based key-derivation function from PKCS#5.

Examples

// generate a password-based 16-byte key// note an optional message digest can be passed as the final parametervarsalt=forge.random.getBytesSync(128);varderivedKey=forge.pkcs5.pbkdf2('password',salt,numIterations,16);// generate key asynchronously// note an optional message digest can be passed before the callbackforge.pkcs5.pbkdf2('password',salt,numIterations,16,function(err,derivedKey){// do something w/derivedKey});
### PKCS#7

Provides cryptographically protected messages from PKCS#7.

Examples

// convert a message from PEMvarp7=forge.pkcs7.messageFromPem(pem);// look at p7.recipients// find a recipient by the issuer of a certificatevarrecipient=p7.findRecipient(cert);// decryptp7.decrypt(p7.recipients[0],privateKey);// create a p7 enveloped messagevarp7=forge.pkcs7.createEnvelopedData();// add a recipientvarcert=forge.pki.certificateFromPem(certPem);p7.addRecipient(cert);// set contentp7.content=forge.util.createBuffer('Hello');// encryptp7.encrypt();// convert message to PEMvarpem=forge.pkcs7.messageToPem(p7);// create a degenerate PKCS#7 certificate container// (CRLs not currently supported, only certificates)varp7=forge.pkcs7.createSignedData();p7.addCertificate(certOrCertPem1);p7.addCertificate(certOrCertPem2);varpem=forge.pkcs7.messageToPem(p7);// create PKCS#7 signed data with authenticatedAttributes// attributes include: PKCS#9 content-type, message-digest, and signing-timevarp7=forge.pkcs7.createSignedData();p7.content=forge.util.createBuffer('Some content to be signed.','utf8');p7.addCertificate(certOrCertPem);p7.addSigner({key: privateKeyAssociatedWithCert,certificate: certOrCertPem,digestAlgorithm: forge.pki.oids.sha256,authenticatedAttributes: [{type: forge.pki.oids.contentType,value: forge.pki.oids.data},{type: forge.pki.oids.messageDigest// value will be auto-populated at signing time},{type: forge.pki.oids.signingTime,// value can also be auto-populated at signing timevalue: newDate()}]});p7.sign();varpem=forge.pkcs7.messageToPem(p7);
### PKCS#8

Examples

varpki=forge.pki;// convert a PEM-formatted private key to a Forge private keyvarprivateKey=pki.privateKeyFromPem(pem);// convert a Forge private key to PEM-formatvarpem=pki.privateKeyToPem(privateKey);// convert an ASN.1 PrivateKeyInfo or RSAPrivateKey to a Forge private keyvarprivateKey=pki.privateKeyFromAsn1(rsaPrivateKey);// convert a Forge private key to an ASN.1 RSAPrivateKeyvarrsaPrivateKey=pki.privateKeyToAsn1(privateKey);// wrap an RSAPrivateKey ASN.1 object in a PKCS#8 ASN.1 PrivateKeyInfovarprivateKeyInfo=pki.wrapRsaPrivateKey(rsaPrivateKey);// convert a PKCS#8 ASN.1 PrivateKeyInfo to PEMvarpem=pki.privateKeyInfoToPem(privateKeyInfo);// encrypts a PrivateKeyInfo and outputs an EncryptedPrivateKeyInfovarencryptedPrivateKeyInfo=pki.encryptPrivateKeyInfo(privateKeyInfo,'password',{algorithm: 'aes256',// 'aes128', 'aes192', 'aes256', '3des'});// decrypts an ASN.1 EncryptedPrivateKeyInfovarprivateKeyInfo=pki.decryptPrivateKeyInfo(encryptedPrivateKeyInfo,'password');// converts an EncryptedPrivateKeyInfo to PEMvarpem=pki.encryptedPrivateKeyToPem(encryptedPrivateKeyInfo);// converts a PEM-encoded EncryptedPrivateKeyInfo to ASN.1 formatvarencryptedPrivateKeyInfo=pki.encryptedPrivateKeyFromPem(pem);// wraps and encrypts a Forge private key and outputs it in PEM formatvarpem=pki.encryptRsaPrivateKey(privateKey,'password');// encrypts a Forge private key and outputs it in PEM format using OpenSSL's// proprietary legacy format + encapsulated PEM headers (DEK-Info)varpem=pki.encryptRsaPrivateKey(privateKey,'password',{legacy: true});// decrypts a PEM-formatted, encrypted private keyvarprivateKey=pki.decryptRsaPrivateKey(pem,'password');// sets an RSA public key from a private keyvarpublicKey=pki.setRsaPublicKey(privateKey.n,privateKey.e);
### PKCS#10

Provides certification requests or certificate signing requests (CSR) from PKCS#10.

Examples

// generate a key pairvarkeys=forge.pki.rsa.generateKeyPair(1024);// create a certification request (CSR)varcsr=forge.pki.createCertificationRequest();csr.publicKey=keys.publicKey;csr.setSubject([{name: 'commonName',value: 'example.org'},{name: 'countryName',value: 'US'},{shortName: 'ST',value: 'Virginia'},{name: 'localityName',value: 'Blacksburg'},{name: 'organizationName',value: 'Test'},{shortName: 'OU',value: 'Test'}]);// set (optional) attributescsr.setAttributes([{name: 'challengePassword',value: 'password'},{name: 'unstructuredName',value: 'My Company, Inc.'},{name: 'extensionRequest',extensions: [{name: 'subjectAltName',altNames: [{// 2 is DNS typetype: 2,value: 'test.domain.com'},{type: 2,value: 'other.domain.com',},{type: 2,value: 'www.domain.net'}]}]}]);// sign certification requestcsr.sign(keys.privateKey);// verify certification requestvarverified=csr.verify();// convert certification request to PEM-formatvarpem=forge.pki.certificationRequestToPem(csr);// convert a Forge certification request from PEM-formatvarcsr=forge.pki.certificationRequestFromPem(pem);// get an attributecsr.getAttribute({name: 'challengePassword'});// get extensions arraycsr.getAttribute({name: 'extensionRequest'}).extensions;
### PKCS#12

Provides the cryptographic archive file format from PKCS#12.

Examples

// decode p12 from base64varp12Der=forge.util.decode64(p12b64);// get p12 as ASN.1 objectvarp12Asn1=forge.asn1.fromDer(p12Der);// decrypt p12 using the password 'password'varp12=forge.pkcs12.pkcs12FromAsn1(p12Asn1,'password');// decrypt p12 using non-strict parsing mode (resolves some ASN.1 parse errors)varp12=forge.pkcs12.pkcs12FromAsn1(p12Asn1,false,'password');// decrypt p12 using literally no password (eg: Mac OS X/apple push)varp12=forge.pkcs12.pkcs12FromAsn1(p12Asn1);// decrypt p12 using an "empty" password (eg: OpenSSL with no password input)varp12=forge.pkcs12.pkcs12FromAsn1(p12Asn1,'');// p12.safeContents is an array of safe contents, each of// which contains an array of safeBags// get bags by friendlyNamevarbags=p12.getBags({friendlyName: 'test'});// bags are key'd by attribute type (here "friendlyName")// and the key values are an array of matching objectsvarcert=bags.friendlyName[0];// get bags by localKeyIdvarbags=p12.getBags({localKeyId: buffer});// bags are key'd by attribute type (here "localKeyId")// and the key values are an array of matching objectsvarcert=bags.localKeyId[0];// get bags by localKeyId (input in hex)varbags=p12.getBags({localKeyIdHex: '7b59377ff142d0be4565e9ac3d396c01401cd879'});// bags are key'd by attribute type (here "localKeyId", *not* "localKeyIdHex")// and the key values are an array of matching objectsvarcert=bags.localKeyId[0];// get bags by typevarbags=p12.getBags({bagType: forge.pki.oids.certBag});// bags are key'd by bagType and each bagType key's value// is an array of matches (in this case, certificate objects)varcert=bags[forge.pki.oids.certBag][0];// get bags by friendlyName and filter on bag typevarbags=p12.getBags({friendlyName: 'test',bagType: forge.pki.oids.certBag});// get key bagsvarbags=p12.getBags({bagType: forge.pki.oids.keyBag});// get keyvarbag=bags[forge.pki.oids.keyBag][0];varkey=bag.key;// if the key is in a format unrecognized by forge then// bag.key will be `null`, use bag.asn1 to get the ASN.1// representation of the keyif(bag.key===null){varkeyAsn1=bag.asn1;// can now convert back to DER/PEM/etc for export}// generate a p12 using AES (default)varp12Asn1=forge.pkcs12.toPkcs12Asn1(privateKey,certificateChain,'password');// generate a p12 that can be imported by Chrome/Firefox// (requires the use of Triple DES instead of AES)varp12Asn1=forge.pkcs12.toPkcs12Asn1(privateKey,certificateChain,'password',{algorithm: '3des'});// base64-encode p12varp12Der=forge.asn1.toDer(p12Asn1).getBytes();varp12b64=forge.util.encode64(p12Der);// create download link for p12vara=document.createElement('a');a.download='example.p12';a.setAttribute('href','data:application/x-pkcs12;base64,'+p12b64);a.appendChild(document.createTextNode('Download'));
### ASN.1

Provides ASN.1 DER encoding and decoding.

Examples

varasn1=forge.asn1;// create a SubjectPublicKeyInfovarsubjectPublicKeyInfo=asn1.create(asn1.Class.UNIVERSAL,asn1.Type.SEQUENCE,true,[// AlgorithmIdentifierasn1.create(asn1.Class.UNIVERSAL,asn1.Type.SEQUENCE,true,[// algorithmasn1.create(asn1.Class.UNIVERSAL,asn1.Type.OID,false,asn1.oidToDer(pki.oids['rsaEncryption']).getBytes()),// parameters (null)asn1.create(asn1.Class.UNIVERSAL,asn1.Type.NULL,false,'')]),// subjectPublicKeyasn1.create(asn1.Class.UNIVERSAL,asn1.Type.BITSTRING,false,[// RSAPublicKeyasn1.create(asn1.Class.UNIVERSAL,asn1.Type.SEQUENCE,true,[// modulus (n)asn1.create(asn1.Class.UNIVERSAL,asn1.Type.INTEGER,false,_bnToBytes(key.n)),// publicExponent (e)asn1.create(asn1.Class.UNIVERSAL,asn1.Type.INTEGER,false,_bnToBytes(key.e))])])]);// serialize an ASN.1 object to DER formatvarderBuffer=asn1.toDer(subjectPublicKeyInfo);// deserialize to an ASN.1 object from a byte buffer filled with DER datavarobject=asn1.fromDer(derBuffer);// convert an OID dot-separated string to a byte buffervarderOidBuffer=asn1.oidToDer('1.2.840.113549.1.1.5');// convert a byte buffer with a DER-encoded OID to a dot-separated stringconsole.log(asn1.derToDer(derOidBuffer));// output: 1.2.840.113549.1.1.5// validates that an ASN.1 object matches a particular ASN.1 structure and// captures data of interest from that structure for easy accessvarpublicKeyValidator={name: 'SubjectPublicKeyInfo',tagClass: asn1.Class.UNIVERSAL,type: asn1.Type.SEQUENCE,constructed: true,captureAsn1: 'subjectPublicKeyInfo',value: [{name: 'SubjectPublicKeyInfo.AlgorithmIdentifier',tagClass: asn1.Class.UNIVERSAL,type: asn1.Type.SEQUENCE,constructed: true,value: [{name: 'AlgorithmIdentifier.algorithm',tagClass: asn1.Class.UNIVERSAL,type: asn1.Type.OID,constructed: false,capture: 'publicKeyOid'}]},{// subjectPublicKeyname: 'SubjectPublicKeyInfo.subjectPublicKey',tagClass: asn1.Class.UNIVERSAL,type: asn1.Type.BITSTRING,constructed: false,value: [{// RSAPublicKeyname: 'SubjectPublicKeyInfo.subjectPublicKey.RSAPublicKey',tagClass: asn1.Class.UNIVERSAL,type: asn1.Type.SEQUENCE,constructed: true,optional: true,captureAsn1: 'rsaPublicKey'}]}]};varcapture={};varerrors=[];if(!asn1.validate(publicKeyValidator,subjectPublicKeyInfo,validator,capture,errors)){throw'ASN.1 object is not a SubjectPublicKeyInfo.';}// capture.subjectPublicKeyInfo contains the full ASN.1 object// capture.rsaPublicKey contains the full ASN.1 object for the RSA public key// capture.publicKeyOid only contains the value for the OIDvaroid=asn1.derToOid(capture.publicKeyOid);if(oid!==pki.oids['rsaEncryption']){throw'Unsupported OID.';}// pretty print an ASN.1 object to a string for debugging purposesasn1.prettyPrint(object);

Message Digests

### SHA1

Provides SHA-1 message digests.

Examples

varmd=forge.md.sha1.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
### SHA256

Provides SHA-256 message digests.

Examples

varmd=forge.md.sha256.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592
### SHA384

Provides SHA-384 message digests.

Examples

varmd=forge.md.sha384.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1
### SHA512

Provides SHA-512 message digests.

Examples

// SHA-512varmd=forge.md.sha512.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: 07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6// SHA-512/224varmd=forge.md.sha512.sha224.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: 944cd2847fb54558d4775db0485a50003111c8e5daa63fe722c6aa37// SHA-512/256varmd=forge.md.sha512.sha256.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: dd9d67b371519c339ed8dbd25af90e976a1eeefd4ad3d889005e532fc5bef04d
### MD5

Provides MD5 message digests.

Examples

varmd=forge.md.md5.create();md.update('The quick brown fox jumps over the lazy dog');console.log(md.digest().toHex());// output: 9e107d9d372bb6826bd81d3542a419d6
### HMAC

Provides HMAC w/any supported message digest algorithm.

Examples

varhmac=forge.hmac.create();hmac.start('sha1','Jefe');hmac.update('what do ya want for nothing?');console.log(hmac.digest().toHex());// output: effcdf6ae5eb2fa2d27416d5f184df9c259a7c79

Utilities

### Prime

Provides an API for generating large, random, probable primes.

Examples

// generate a random prime on the main JS threadvarbits=1024;forge.prime.generateProbablePrime(bits,function(err,num){console.log('random prime',num.toString(16));});// generate a random prime using Web Workers (if available, otherwise// falls back to the main thread)varbits=1024;varoptions={algorithm: {name: 'PRIMEINC',workers: -1// auto-optimize # of workers}};forge.prime.generateProbablePrime(bits,options,function(err,num){console.log('random prime',num.toString(16));});
### PRNG

Provides a Fortuna-based cryptographically-secure pseudo-random number generator, to be used with a cryptographic function backend, e.g. AES. An implementation using AES as a backend is provided. An API for collecting entropy is given, though if window.crypto.getRandomValues is available, it will be used automatically.

Examples

// get some random bytes synchronouslyvarbytes=forge.random.getBytesSync(32);console.log(forge.util.bytesToHex(bytes));// get some random bytes asynchronouslyforge.random.getBytes(32,function(err,bytes){console.log(forge.util.bytesToHex(bytes));});// collect some entropy if you'd likeforge.random.collect(someRandomBytes);jQuery().mousemove(function(e){forge.random.collectInt(e.clientX,16);forge.random.collectInt(e.clientY,16);});// specify a seed file for use with the synchronous API if you'd likeforge.random.seedFileSync=function(needed){// get 'needed' number of random bytes from somewherereturnfetchedRandomBytes;};// specify a seed file for use with the asynchronous API if you'd likeforge.random.seedFile=function(needed,callback){// get the 'needed' number of random bytes from somewherecallback(null,fetchedRandomBytes);});// register the main thread to send entropy or a Web Worker to receive// entropy on demand from the main threadforge.random.registerWorker(self);// generate a new instance of a PRNG with no collected entropyvarmyPrng=forge.random.createInstance();
### Tasks

Provides queuing and synchronizing tasks in a web application.

Examples

### Utilities

Provides utility functions, including byte buffer support, base64, bytes to/from hex, zlib inflate/deflate, etc.

Examples

// encode/decode base64varencoded=forge.util.encode64(str);varstr=forge.util.decode64(encoded);// encode/decode UTF-8varencoded=forge.util.encodeUtf8(str);varstr=forge.util.decodeUtf8(encoded);// bytes to/from hexvarbytes=forge.util.hexToBytes(hex);varhex=forge.util.bytesToHex(bytes);// create an empty byte buffervarbuffer=forge.util.createBuffer();// create a byte buffer from raw binary bytesvarbuffer=forge.util.createBuffer(input,'raw');// create a byte buffer from utf8 bytesvarbuffer=forge.util.createBuffer(input,'utf8');// get the length of the buffer in bytesbuffer.length();// put bytes into the bufferbuffer.putBytes(bytes);// put a 32-bit integer into the bufferbuffer.putInt32(10);// buffer to hexbuffer.toHex();// get a copy of the bytes in the bufferbytes.bytes(/* count */);// empty this buffer and get its contentsbytes.getBytes(/* count */);// convert a forge buffer into a node.js Buffer// make sure you specify the encoding as 'binary'varforgeBuffer=forge.util.createBuffer();varnodeBuffer=newBuffer(forgeBuffer.getBytes(),'binary');// convert a node.js Buffer into a forge buffer// make sure you specify the encoding as 'binary'varnodeBuffer=newBuffer();varforgeBuffer=forge.util.createBuffer(nodeBuffer.toString('binary'));// parse a URLvarparsed=forge.util.parseUrl('http://example.com/foo?bar=baz');// parsed.scheme, parsed.host, parsed.port, parsed.path, parsed.fullHost
### Logging

Provides logging to a javascript console using various categories and levels of verbosity.

Examples

### Debugging

Provides storage of debugging information normally inaccessible in closures for viewing/investigation.

Examples

### Flash Socket Policy Module

Provides an Apache module "mod_fsp" that can serve up a Flash Socket Policy. See mod_fsp/README for more details. This module makes it easy to modify an Apache server to allow cross domain requests to be made to it.

Library Details

Contact

Donations welcome:

About

A native implementation of TLS in Javascript and tools to write crypto-based and network-heavy webapps

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages