PeculiarVentures / PKI.js

PKI.js is a pure JavaScript library implementing the formats that are used in PKI applications (signing, encryption, certificate requests, OCSP and TSP requests/responses). It is built on WebCrypto (Web Cryptography API) and requires no plug-ins.
http://pkijs.org
Other
1.25k stars 204 forks source link

Getting thumbprint from certificate file #295

Closed coolassassin closed 3 years ago

coolassassin commented 3 years ago

Hello, i am trying to get thumbprint(hash) of certificate. I have found this page: https://pkijs.org/examples/CRL_complex_example.html It works fine with my certificate, but there is not hash there. Could I get it somehow?

YuryStrozhevsky commented 3 years ago
const crypto = getCrypto();
if(typeof crypto === "undefined")
    return "Unable to create WebCrypto object";

const thumbprint = await crypto.digest({ name: "sha-1" }, new Uint8Array(certificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex));
coolassassin commented 3 years ago

Thank you.

I have made script like this:

import * as asn1js from "asn1js";
import { Certificate, getCrypto } from "pkijs";

const toHex = (n) => {
  if (n < 16) return "0" + n.toString(16);
  return n.toString(16);
};

const ArrayBufferToString = (buffer) => {
  const uint8 = new Uint8Array(buffer);
  let out = "";
  for (let i = 0, l = uint8.byteLength; i < l; ++i) {
    out += toHex(uint8[i]);
  }
  return out;
};

const parseCertificate = async (buffer) => {
  const crypto = getCrypto();
  const asn1 = asn1js.fromBER(buffer);
  const certificate = new Certificate({ schema: asn1.result });
  const thumbprint = await crypto.digest(
    { name: "sha-1" },
    new Uint8Array(
      certificate.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex
    )
  );
  console.log(ArrayBufferToString(thumbprint)); /// <<-- Wrong ☹
};

document.addEventListener("DOMContentLoaded", () => {
  document.getElementById("file").addEventListener("change", (ev) => {
    const tempReader = new FileReader();
    const currentFiles = ev.target.files;

    tempReader.onload = (event) => {
      parseCertificate(event.target.result);
    };

    tempReader.readAsArrayBuffer(currentFiles[0]);
  });
});

But i have wrong hash in result. If i open file in windows app for certificates i see another one.

rmhrisk commented 3 years ago

Not sure what you're trying to do but you may be more interested in the [certificate viewer] which takes care getting a reasonable representation of values out of a certificate for users.(https://github.com/PeculiarVentures/pv-certificates-viewer).

image

Even if not you can look at the code there to see what values you need to hash to get the matching thumbprint you are looking for.

coolassassin commented 3 years ago

I got what is the problem. My script gives me ID. But i need hash. изображение Look at the picture. First one - it is what i get with my script. But i need the last one.

rmhrisk commented 3 years ago

You are hashing the wrong part of the cert, look at our cert viewer to understand what to hash.

YuryStrozhevsky commented 3 years ago
const parseCertificate = async (buffer) => {
  const crypto = getCrypto();
  const thumbprint = await crypto.digest(
    { name: "sha-1" },
    new Uint8Array(
      buffer
    )
  );
  console.log(ArrayBufferToString(thumbprint)); /// <<-- Right
};
coolassassin commented 3 years ago
const parseCertificate = async (buffer) => {
  const crypto = getCrypto();
  const thumbprint = await crypto.digest(
    { name: "sha-1" },
    new Uint8Array(
      buffer
    )
  );
  console.log(ArrayBufferToString(thumbprint)); /// <<-- Right
};

Excellent! It is exactly what i need! Thank you a lot 🙂