node-forge

repository·main·Indexed 26 days ago

https://github.com/digitalbazaar/forge

A native JavaScript implementation of the TLS protocol and a comprehensive suite of cryptographic utilities. It provides implementations for network transports, ciphers (AES, 3DES, DES, RC2), PKI, message digests, and X.509 certificates. Features include RSA key pair generation, ED25519 signing and verification, RSA-KEM for key encapsulation, and SSH utility functions for encoding keys into Putty and OpenSSH formats.

Tokens
14.1K
Snippets
40
Records
56
Agent score
90%

What's inside node-forge

  1. Build the SocketPool.swf Flash component

    main

    Some networking features in Forge optionally use a Flash component. To build the swf/SocketPool.swf component, you must have the mxmlc tool from the Flex SDK installed.

    If you do not have the Flex SDK, you can install it via npm using the command provided in the repository. Once the SDK is available, use the following commands to build the component:

    • To build a regular component: npm run build
    • To build with additional debug support: npm run build-debug
    npm install
    
    # To build a regular component
    npm run build
    
    # To build with additional debug support
    npm run build-debug
  2. Configure a Policy Server for Flash support

    main

    Flash support in Forge requires a Policy Server to allow cross-domain requests. Depending on your environment, you can use one of the following options:

    1. Apache: Use the mod_fsp module to modify an Apache server to serve a Flash Socket Policy. Detailed instructions are available in mod_fsp/README.
    2. Python (Testing only): Use policyserver.py for a simple test policy server.
    3. Node.js (Testing only): Use policyserver.js for a simple test policy server.

    Note: For production environments, do not use the simple Node.js or Python servers provided here. Instead, use a production-ready option like nodejs_socket_policy_server.

  3. Generate and sign an X.509v3 certificate

    main

    You can create a self-signed X.509v3 certificate by generating an RSA keypair, configuring certificate attributes (subject, issuer, validity, and extensions), and signing it with the private key. Forge also provides utilities to convert certificates between PEM, ASN.1, and Forge objects.

    // generate a keypair and create an X.509v3 certificate
    var keys = pki.rsa.generateKeyPair(2048);
    var cert = pki.createCertificate();
    cert.publicKey = keys.publicKey;
    cert.serialNumber = '01';
    cert.validity.notBefore = new Date();
    cert.validity.notAfter = new Date();
    cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
    var attrs = [{
      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);
    cert.setIssuer(attrs);
    cert.setExtensions([{ 
      name: 'basicConstraints', 
      cA: true 
    }]); // ... other extensions
    
    // self-sign certificate
    cert.sign(keys.privateKey);
    
    // convert a Forge certificate to PEM
    var pem = pki.certificateToPem(cert);
    
    // convert a Forge certificate from PEM
    var cert = pki.certificateFromPem(pem);
    
    // convert an ASN.1 X.509v3 object to a Forge certificate
    var cert = pki.certificateFromAsn1(obj);
    
    // convert a Forge certificate to an ASN.1 X.509v3 object
    var asn1Cert = pki.certificateToAsn1(cert);
  4. Match OpenSSL 'enc' command line tool in Node.js

    main

    To replicate OpenSSL's enc behavior (specifically for des3), you must use forge.pbe.opensslDeriveBytes to derive the key and IV from a password and salt. When encrypting, if a salt is used, you must prepend the string 'Salted__' followed by the 8-byte salt to the output buffer to match the OpenSSL file format.

    var derivedBytes = forge.pbe.opensslDeriveBytes(password, salt, keySize + ivSize);
    var buffer = forge.util.createBuffer(derivedBytes);
    var key = buffer.getBytes(keySize);
    var iv = buffer.getBytes(ivSize);
    
    var cipher = forge.cipher.createCipher('3DES-CBC', key);
    cipher.start({iv: iv});
    cipher.update(forge.util.createBuffer(input, 'binary'));
    cipher.finish();
    
    var output = forge.util.createBuffer();
    if(salt !== null) {
      output.putBytes('Salted__');
      output.putBytes(salt);
    }
    output.putBuffer(cipher.output);
  5. Build Forge browser bundles

    main

    To create single-file bundles (both non-minimized and minimized) for use in web browsers, run the following commands. This will generate files in the dist/ directory, such as forge.js and forge.min.js.

    npm install
    npm run build
  6. Connect to a TLS server as a client

    main

    To act as a TLS client, use forge.tls.createConnection with server: false. This is typically used in conjunction with a raw socket (like Node.js net.Socket). You must manually bridge the socket and the Forge TLS connection by calling client.handshake() on socket connection, passing socket data to client.process(data), and writing client.tlsData.getBytes() to the socket when tlsDataReady is triggered.

    var socket = new net.Socket();
    
    var client = forge.tls.createConnection({
      server: false,
      verify: function(connection, verified, depth, certs) {
        return true;
      },
      connected: function(connection) {
        client.prepare('GET / HTTP/1.0\r\n\r\n');
      },
      tlsDataReady: function(connection) {
        var data = connection.tlsData.getBytes();
        socket.write(data, 'binary');
      },
      dataReady: function(connection) {
        var data = connection.data.getBytes();
        console.log('[tls] data received: ' + data);
      },
      closed: function() {},
      error: function(connection, error) {}
    });
    
    socket.on('connect', function() {
      client.handshake();
    });
    socket.on('data', function(data) {
      client.process(data.toString('binary'));
    });
    socket.connect(443, 'google.com');
  7. Configure forge.options.usePureJavaScript

    main

    You can disable the use of native code (which is typically faster and more secure) by setting the forge.options.usePureJavaScript flag to true. This is useful for testing features in environments different from your current one.

    // In the browser (run after including the forge script)
    forge.options.usePureJavaScript = true;
    
    // In Node.js
    var forge = require('node-forge');
    forge.options.usePureJavaScript = true;
  8. Perform symmetric encryption/decryption using BlockCipher

    main

    To encrypt or decrypt data, follow the start -> update -> finish lifecycle using a BlockCipher instance (typically obtained via createCipher or createDecipher).

    1. Start the process

    Call cipher.start(options) to initialize the mode.

    • iv: Initialization vector (binary string, byte array, byte buffer, or 4 32-bit integers). Required for non-ECB modes. For GCM, 12 bytes (96 bits) is recommended.
    • additionalData: (GCM mode only) Additional authentication data.
    • tagLength: (GCM mode only) Authentication tag length in bits (0-128, default 128).
    • tag: (GCM mode only, decryption) The authentication tag to check.
    • output: The buffer to write to (defaults to a new buffer).

    2. Update with data

    Call cipher.update(input) to process chunks of data. input should be a buffer.

    3. Finish the process

    Call cipher.finish(pad) to finalize the operation.

    • pad: A padding function to use in CBC mode. If null, the default padding is used. Returns true if successful, false on error.
  9. Manually install mod_fsp on Apache2

    main

    To manually enable mod_fsp, follow these steps:

    1. Copy the module file: Move fsp.so to your Apache module installation directory (e.g., /usr/lib/apache2/modules on Debian).
    2. Create a load file: Create a file named fsp.load in the Apache mods-available directory (e.g., /etc/apache2/mods-available on Debian) with the following content: LoadModule fsp_module /usr/lib/apache2/modules/mod_fsp.so (adjust the path if your installation directory differs).
    3. Enable the module: Create a symbolic link from the mods-available directory to the mods-enabled directory (e.g., /etc/apache2/mods-enabled on Debian).
    ln -s ../mods-available/fsp.load fsp.load