ctutils
Version:
Utilities for interacting with Certificate Transparency logs
124 lines (104 loc) • 3.93 kB
JavaScript
/**
* Certificate Transparency Utilities
* TimestampedEntry class
*
* By Fotis Loukos <me@fotisl.com>
* @module ctutils
*/
import { uint64ToArrayBuffer, arrayBufferToUint64 } from './Common';
import { LogEntryType } from './Enums';
/**
* TimestampedEntry class
*/
export default class TimestampedEntry {
/**
* Construct a TimestampedEntry.
* @param {number} timestamp - The timestamp of the entry.
* @param {number} type - The type of the entry.
* @param {ArrayBuffer} cert - The certificate or precertificate of the entry.
* @param {ArrayBuffer} extensions - The extensions of the entry.
*/
constructor(timestamp, type, cert, extensions) {
/**
* @type number
* @description The timestamp of the entry.
*/
this.timestamp = timestamp;
/**
* @type number
* @description The type of the entry.
*/
this.type = type;
/**
* @type ArrayBuffer
* @description The certificate or precertificate of the entry.
*/
this.cert = cert;
/**
* @type ArrayBuffer
* @description The extensions of the entry.
*/
this.extensions = extensions;
}
/**
* Encode the entry and get the binary representation.
* @return {ArrayBuffer} An ArrayBuffer containing the binary representation
* of the entry.
*/
toBinary() {
let certView;
let timestampedEntryLen;
const extensionsView = new Uint8Array(this.extensions);
certView = new Uint8Array(this.cert);
if(this.type === LogEntryType.x509_entry)
timestampedEntryLen = 15 + certView.length + extensionsView.length;
else
timestampedEntryLen = 12 + certView.length + extensionsView.length;
const timestampedEntry = new ArrayBuffer(timestampedEntryLen);
const timestampedEntryView = new Uint8Array(timestampedEntry);
timestampedEntryView.set(new Uint8Array(uint64ToArrayBuffer(
this.timestamp)));
timestampedEntryView[8] = (this.type >> 8) & 0xff;
timestampedEntryView[9] = this.type & 0xff;
let offset = 10;
if(this.type === LogEntryType.x509_entry) {
timestampedEntryView[10] = (certView.length >> 16) & 0xff;
timestampedEntryView[11] = (certView.length >> 8) & 0xff;
timestampedEntryView[12] = certView.length & 0xff;
offset += 3;
}
timestampedEntryView.set(certView, offset);
timestampedEntryView[offset + certView.length] =
(extensionsView.length >> 8) & 0xff;
timestampedEntryView[offset + certView.length + 1] =
extensionsView.length & 0xff;
if(extensionsView.length > 0)
timestampedEntryView.set(extensionsView, offset + 2 + certView.length);
return timestampedEntry;
}
/**
* Parse a binary TimestampedEntry and return a new object.
* @param {ArrayBuffer} timestampedEntryBin - The binary TimestampedEntry.
* @return {TimestampedEntry} The TimestampedEntry object.
*/
static fromBinary(timestampedEntryBin) {
const timestampedEntryBinView = new Uint8Array(timestampedEntryBin);
const timestamp = arrayBufferToUint64(
timestampedEntryBinView.slice(0, 8).buffer);
const type = (timestampedEntryBinView[8] << 8) + timestampedEntryBinView[9];
let cert, extensions;
if(type === LogEntryType.x509_entry) {
const certLen = (timestampedEntryBinView[10] << 16) +
(timestampedEntryBinView[11] << 8) + timestampedEntryBinView[12];
cert = timestampedEntryBinView.slice(13, 13 + certLen).buffer;
extensions = timestampedEntryBinView.slice(13 + certLen).buffer;
} else {
let preCertLen = 32;
preCertLen += (timestampedEntryBinView[42] << 16) +
(timestampedEntryBinView[43] << 8) + timestampedEntryBinView[44];
cert = timestampedEntryBinView.slice(10, 10 + preCertLen).buffer;
extensions = timestampedEntryBinView.slice(10 + preCertLen).buffer;
}
return new TimestampedEntry(timestamp, type, cert, extensions);
}
}