securityos/node_modules/resedit/dist/sign/certUtil.js

243 lines
9.6 KiB
JavaScript

import { RawDERObject } from './data/DERObject.js';
import { OID_SIGNED_DATA } from './data/KnownOids.js';
export function toUint8Array(bin) {
if ('buffer' in bin) {
return new Uint8Array(bin.buffer, bin.byteOffset, bin.byteLength);
}
else {
return new Uint8Array(bin);
}
}
/** @return [length, afterOffset] */
export function calculateDERLength(data, offset) {
var actualLength = 0;
if (data[offset] < 0x80) {
actualLength = data[offset];
++offset;
}
else if (data[offset] === 0x80) {
throw new Error('Not supported certificate data (variable length)');
}
else {
var c = data[offset] & 0x7f;
++offset;
while (c--) {
if (offset >= data.length) {
throw new Error('Invalid certificate data (invalid sequence length)');
}
actualLength <<= 8;
actualLength |= data[offset];
++offset;
}
}
return [actualLength, offset];
}
function skipField(data, offsetOfDataHead) {
var _a = calculateDERLength(data, offsetOfDataHead + 1), len = _a[0], off = _a[1];
return off + len;
}
function pickCertificatesIfDERHasSignedData(ub, offset) {
var _a, _b, _c, _d, _e;
if (ub.length < offset + 2) {
return null;
}
if (ub[offset] !== 0x30) {
return null;
}
var tempLength;
_a = calculateDERLength(ub, offset + 1), tempLength = _a[0], offset = _a[1];
if (tempLength > ub.length - offset) {
throw new Error('Invalid certificate data (insufficient data length)');
}
// if the first item is not contentType, then return
if (ub[offset] !== 0x6) {
return null;
}
var signedDataOid = OID_SIGNED_DATA.toDER();
for (var i = 0; i < signedDataOid.length; ++i) {
if (ub[offset + i] !== signedDataOid[i]) {
return null;
}
}
// if contentType is OID_SIGNED_DATA, then check sequence format
// ContentInfo.content
offset += signedDataOid.length;
// [0] IMPLICIT
if (ub[offset] !== 0xa0) {
throw new Error('Invalid certificate data (no content in contentInfo)');
}
_b = calculateDERLength(ub, offset + 1), tempLength = _b[0], offset = _b[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for content)');
}
// sequence
if (ub[offset] !== 0x30) {
throw new Error('Invalid certificate data (unexpected signedData)');
}
_c = calculateDERLength(ub, offset + 1), tempLength = _c[0], offset = _c[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData)');
}
// version
if (ub[offset] !== 0x2 ||
ub[offset + 1] !== 0x1 ||
ub[offset + 2] !== 0x1) {
throw new Error('Invalid certificate data (unexpected signedData.version)');
}
offset += 3;
// digestAlgorithms (skip)
if (ub[offset] !== 0x31) {
throw new Error('Invalid certificate data (no signedData.digestAlgorithms)');
}
_d = calculateDERLength(ub, offset + 1), tempLength = _d[0], offset = _d[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.digestAlgorithms)');
}
offset += tempLength;
// contentInfo (skip)
if (ub[offset] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.contentInfo)');
}
_e = calculateDERLength(ub, offset + 1), tempLength = _e[0], offset = _e[1];
if (offset + tempLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.contentInfo)');
}
offset += tempLength;
// certificates
if (ub[offset] !== 0xa0) {
throw new Error('Invalid certificate data (no signedData.certificates)');
}
var _f = calculateDERLength(ub, offset + 1), certsLength = _f[0], newOffset = _f[1];
if (newOffset + certsLength > ub.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
return ub.subarray(offset, newOffset + certsLength);
}
/** @return [issuer, serialNumber] */
export function pickIssuerAndSerialNumberDERFromCert(bin) {
var _a, _b;
if (Array.isArray(bin)) {
// use first one and call again
if (bin.length === 0) {
throw new Error('No data is specified.');
}
return pickIssuerAndSerialNumberDERFromCert(bin[0]);
}
var ub = toUint8Array(bin);
if (ub.length < 2) {
throw new Error('Invalid certificate data');
}
if (ub[0] !== 0x30) {
throw new Error('Not supported certificate data (non-`Certificate`-format data)');
}
var certsBin = pickCertificatesIfDERHasSignedData(ub, 0);
if (certsBin) {
// certificates
var _c = calculateDERLength(certsBin, 1), tempLength_1 = _c[0], eaten_1 = _c[1];
if (eaten_1 + tempLength_1 > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
// pick first certificate and call again
if (certsBin[eaten_1] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.certificates[0])');
}
var _d = calculateDERLength(certsBin, eaten_1 + 1), certLength = _d[0], tempOffset = _d[1];
if (tempOffset + certLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates[0])');
}
return pickIssuerAndSerialNumberDERFromCert(certsBin.subarray(eaten_1, tempOffset + certLength));
}
var tempLength;
var eaten;
_a = calculateDERLength(ub, 1), tempLength = _a[0], eaten = _a[1];
if (tempLength > ub.length - eaten) {
throw new Error('Invalid certificate data (insufficient data length)');
}
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (missing tbsCertificate)');
}
// Certificate
var tbsCertificateLen;
_b = calculateDERLength(ub, eaten + 1), tbsCertificateLen = _b[0], eaten = _b[1];
if (tbsCertificateLen > ub.length - eaten) {
throw new Error('Invalid certificate data (invalid tbsCertificate length)');
}
var tbsOffsetLast = eaten + tbsCertificateLen;
// TBSCertificate
// :skip version
if (ub[eaten] === 0xa0) {
eaten = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after version)');
}
}
// pick serialNumber
if (ub[eaten] !== 2) {
throw new Error('Invalid certificate data (invalid serialNumber)');
}
var offsetAfterSerialNumber = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after serialNumber)');
}
var serialNumberDER = [].slice.call(ub, eaten, offsetAfterSerialNumber);
eaten = offsetAfterSerialNumber;
// :skip algorithmIdentifier
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (invalid algorithmIdentifier)');
}
eaten = skipField(ub, eaten);
if (eaten >= tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: after serialNumber)');
}
// pick issuer
// Name ::= CHOICE { RDNSequence }
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
if (ub[eaten] !== 0x30) {
throw new Error('Invalid certificate data (invalid issuer)');
}
var offsetAfterIssuer = skipField(ub, eaten);
if (offsetAfterIssuer > tbsOffsetLast) {
throw new Error('Invalid certificate data (insufficient tbsCertificate data: issuer)');
}
return [
// return entire issuer sequence
[].slice.call(ub, eaten, offsetAfterIssuer),
serialNumberDER,
];
}
export function certBinToCertificatesDER(bin) {
if (Array.isArray(bin)) {
// use all items, map with `certBinToCertificatesDER`, and concat all
return bin
.map(certBinToCertificatesDER)
.reduce(function (prev, cur) { return prev.concat(cur); }, []);
}
var ub = toUint8Array(bin);
var certsBin = pickCertificatesIfDERHasSignedData(ub, 0);
if (certsBin) {
// certificates
var _a = calculateDERLength(certsBin, 1), tempLength = _a[0], eaten = _a[1];
if (eaten + tempLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates)');
}
var offsetLast = eaten + tempLength;
var rawData = [];
for (var offset = eaten; offset < offsetLast;) {
// pick certificates
if (certsBin[offset] !== 0x30) {
throw new Error('Invalid certificate data (no signedData.certificates[*])');
}
var _b = calculateDERLength(certsBin, offset + 1), certLength = _b[0], tempOffset = _b[1];
if (tempOffset + certLength > certsBin.length) {
throw new Error('Invalid certificate data (invalid length for signedData.certificates[*])');
}
rawData.push(new RawDERObject(certsBin.subarray(offset, tempOffset + certLength)));
offset = tempOffset + certLength;
}
return rawData;
}
else {
return [new RawDERObject(ub)];
}
}