node.jsopenssl

Replicating "openssl sha1" in Node


How do I replicate the functionality of openssl sha1 in pure Node? I've tried the code below, but I get different results when I run it versus when I do openssl sha1

const crypto = require('crypto');
const key = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA50usDP38lUfcpTKmiGEt
oIeUQlJbSZi8/FNshil+Wf4/oyWPtzQeZL9NoWvtDoQit5dRpRU+5c2e5j3iYlOl
JcfBX6S/HRdrJHD8xirsNRVSMq4woQbd2QcniX1fwWLhJDU8XNaTYwEGQSTnkzxA
NpvwXMixAip+Nr0YMnZOToR6gu0t0euCUWpiypr/Zm40ppeAYxZzghHcVB4zbkOB
zN0h1rIRQ6It7fv12Kd3u6semGCEtJcYBo0ZJsucRQDUpTTGzuEChI35/Q94W4QH
evQ+JD68G2jQ/eOknYHoVUdjTYh3GJaiOpu+GDJXu3GHK18JjZmM0Lsmw/Jbypfj
wwIDAQAB
-----END PUBLIC KEY-----`;

const sha1 = (str) => crypto.createHash('sha1').update(str).digest('hex');

pem.promisified.getPublicKey(key).then(({publicKey}) => {
  // Remove BEGIN and END blocks, newlines
  const stripped = publicKey.replace(/-----BEGIN.+KEY-----/, '').replace(/-----END.+KEY-----/,'').replaceAll('\n','');
  // Remove BEGIN and END blocks only
  const stripped2 = publicKey.replace(/-----BEGIN.+KEY-----/, '').replace(/-----END.+KEY-----/,'');
  // Remove newlines only
  const stripped3 = publicKey.replaceAll('\n','');

  console.debug("SHA1: ", sha1(publicKey));
  console.debug("SHA1 (stripped): ", sha1(stripped));
  console.debug("SHA1 (stripped2): ", sha1(stripped2));
  console.debug("SHA1 (stripped3): ", sha1(stripped3));
});

This outputs:

SHA1:  2f9ab4bb70dafe6e41e401977fabea42da4c0161
SHA1 (stripped):  7cf7d0322f96221d2075123b86c5095885d5025a
SHA1 (stripped2):  58a3c4ca8e5bd33b2d2b72ea6c5bff477b743c45
SHA1 (stripped3):  f80da8adcb7362fd7bd290fa6023f4b7d35a8757

By comparison, openssl sha1 calculates a digest of 64166b841bbb61c3f0dd7cefebb62bd79debce66. How do I get this SHA1 without invoking the openssl binary?


Solution

  • H/T: dave_thompson_085 for figuring out it was the newline all along.

    The problem was that my public key didn't have a trailing newline. Updated sketch (minus all the stripping):

    const pem = require('pem');
    const crypto = require('crypto');
    
    const key = `-----BEGIN PRIVATE KEY-----
    MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDnS6wM/fyVR9yl
    MqaIYS2gh5RCUltJmLz8U2yGKX5Z/j+jJY+3NB5kv02ha+0OhCK3l1GlFT7lzZ7m
    PeJiU6Ulx8FfpL8dF2skcPzGKuw1FVIyrjChBt3ZByeJfV/BYuEkNTxc1pNjAQZB
    JOeTPEA2m/BcyLECKn42vRgydk5OhHqC7S3R64JRamLKmv9mbjSml4BjFnOCEdxU
    HjNuQ4HM3SHWshFDoi3t+/XYp3e7qx6YYIS0lxgGjRkmy5xFANSlNMbO4QKEjfn9
    D3hbhAd69D4kPrwbaND946SdgehVR2NNiHcYlqI6m74YMle7cYcrXwmNmYzQuybD
    8lvKl+PDAgMBAAECggEANgEfLPFotlpPFGtdIt69zouZfFrKYca96ZR49GJf1Bdf
    OHKeucH7jr50G8qdURRdHszADXGGfBWkklHEt/ybxNR9PB21Wc+L/rg67PI8sLBH
    vvmY9SArUG8xNhMF9ptlwhSEAZFAXI9yrGc3gtNAkv+aAbACVGUjjxhbu/yPkBlA
    1Hg3sMcahgY1iXRmWSodTLwuRFPxAiexq/61EuCwdjUR/rhjCdl4HQFCv3m2VaCG
    ZfuHZ9Wu3dU+ZN3eAjK1lGeVBzDppz1HwLsATbYxCOlHf8BO/UL+xvZE0Eu/46KW
    B6gl+VKQejiG/Y2VbZCoSO4aOhtR9q0WKToqMpmowQKBgQD/oFQZoJYh30+j8TuA
    eaQgh9n/paM7/FQUwmgp1ToZKJ9zMewz5H5hIdXDdq6Z6ICEXNwXZfxfB+CuXtXk
    ovN6BxPRhvnaDbb4u7KrWcg1XXEZMtyNXTgf75JMmiFD3gCbthVY4zv2a16odLlQ
    g1ufU7+A2l3p84eYucFUiJh0EwKBgQDnojzLXif70Ef9hlPBN0NLlP7VN5udI0qM
    HdV4wf7QJpuREZxg9vAa/Bt+bJrH9Ar7juZoO1jLm0NRA+pK/QRbZu8t+2pFvSgP
    pI7ORC0i3lXMsUcrEc5i7aTDNWPrHA6081O0nld2XH0Sl6bij7+dmia5pexvmplb
    z8P1nJvnkQKBgD6rTNL3lrb5K2oy4vaNW9qJ070kG4/CPc7VFnpjBxpR5j10mMbk
    FsOzate/yfB7mr5YkbC+1Q9rO/8jyuaBuJVLFOXCZJC72gbC5XuyyC2lGewmlwGl
    P/Q8ZK6Y/tzHmXiTPEqNcw7npc5Ax4ngml7GRmXNo0aO6MhdifMyhcW3AoGADSFa
    NuEAfTrCSfHKX6KFUwyAIZAEZzTv7d9nEXBVxHDb0q5f4fM9ixoNaO45G+qOkNH5
    56CtmOUVPMtvBY8wJwo/tqiQzqE5WyGl4rVkpZxa2r6V3TAmNd9ovpQRNOujPcip
    TwzGwnPdtycXk7I4V3O8jDuGmpD17olpf0vAXrECgYEA9ZtG+7Z7DiFwEY3t18sh
    80NwlFumK4NMEoB5RNjvuFJV6DGQDhL3XeFF9q5pDPCdeakF7HdaOik6GUIxMTHq
    tJSt9a32QOUQoY0SHzSwzo+9oN54gDBIT0iHhiclGaK8eY+Hs9fVQcS6y2VhRBjY
    a7e6XwIj+25nKZZtGudD0/w=
    -----END PRIVATE KEY-----`
    
    const sha1 = (str) => crypto.createHash('sha1').update(str).digest('hex');
    
    pem.promisified.getPublicKey(key).then(({publicKey}) => {
      // getPublicKey doesn't append a newline
      publicKey = publicKey + '\n';
      console.debug({publicKey});
      console.debug("SHA1: ", sha1(publicKey));
    });