Skip to content

Commit

Permalink
feat(viewer): added support "SubjectDirectoryAttributes" extension
Browse files Browse the repository at this point in the history
  • Loading branch information
donskov committed Aug 11, 2020
1 parent 83543b8 commit ea7432f
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Convert } from 'pvtsutils';
import { Attribute } from '@peculiar/asn1-x509';

export function getAttributeValue(attribute: Attribute) {
return Convert.ToString(attribute.values[0]);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { h, FunctionalComponent } from '@stencil/core';

import { Extension } from '../../../crypto/extension';
import { Extension, TExtensionValue } from '../../../crypto/extension';
import { getStringByOID } from '../get_string_by_oid';
import { RowValue } from '../row';

interface IBasicExtensionProps {
extension: Extension;
extension: Extension<TExtensionValue>;
}

export const BasicExtension: FunctionalComponent<IBasicExtensionProps> = (props, children) => {
Expand Down
14 changes: 12 additions & 2 deletions src/components/certificate-viewer/extensions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CertificatePolicies,
NameConstraints,
CRLReason,
SubjectDirectoryAttributes,
} from '@peculiar/asn1-x509';
import { CertificateTransparency } from '@peculiar/asn1-cert-transparency';
import {
Expand All @@ -24,7 +25,7 @@ import { LeiRoles, LeiChoice } from '@peculiar/asn1-lei';
import { Timestamp, ArchiveRevInfo } from '@peculiar/asn1-adobe-acrobat';

import { RowTitle } from '../row';
import { Extension } from '../../../crypto/extension';
import { Extension, TExtensionValue } from '../../../crypto/extension';

import { KeyUsageExtension } from './key_usage_extension';
import { BasicConstraintsExtension } from './basic_constraints_extension';
Expand All @@ -48,6 +49,7 @@ import { LeiExtension } from './lei_extension';
import { TimestampExtension } from './timestamp_extension';
import { ArchiveRevInfoExtension } from './archive_rev_info_extension';
import { CRLReasonExtension } from './crl_reason_extension';
import { SubjectDirectoryAttributesExtension } from './subject_directory_attributes_extension';
import { AsStringExtension } from './as_string_extension';
import { BasicExtension } from './basic_extension';

Expand All @@ -57,7 +59,7 @@ interface IExtensionsProps extends
IAuthorityKeyIdentifierOptions,
ISubjectKeyIdentifierOptions
{
extensions: Extension[];
extensions: Extension<TExtensionValue>[];
}

export const Extensions: FunctionalComponent<IExtensionsProps> = (props) => {
Expand Down Expand Up @@ -257,6 +259,14 @@ export const Extensions: FunctionalComponent<IExtensionsProps> = (props) => {
);
}

if (extension.value instanceof SubjectDirectoryAttributes) {
return (
<SubjectDirectoryAttributesExtension
extension={extension as any}
/>
);
}

if (typeof extension.value === 'string') {
return (
<AsStringExtension
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { h, FunctionalComponent } from '@stencil/core';
import { SubjectDirectoryAttributes } from '@peculiar/asn1-x509';

import { Extension } from '../../../crypto/extension';
import { RowValue } from '../row';
import { getStringByOID } from '../get_string_by_oid';

import { BasicExtension } from './basic_extension';
import { getAttributeValue } from './attribute_value';

interface ISubjectDirectoryAttributesExtensionProps {
extension: Extension<SubjectDirectoryAttributes>;
}

export const SubjectDirectoryAttributesExtension:
FunctionalComponent<ISubjectDirectoryAttributesExtensionProps> = (props) => {
const { extension } = props;

return (
<BasicExtension
extension={extension}
>
{extension.value.map((attribute, index) => ([
<RowValue
name={`Attribute #${index + 1}`}
value={getStringByOID(attribute.type)}
/>,
<RowValue
name={`Value #${index + 1}`}
value={getAttributeValue(attribute)}
/>,
<tr>
<td />
<td />
</tr>,
]))}
</BasicExtension>
);
};
65 changes: 34 additions & 31 deletions src/crypto/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,12 @@ export type TExtensionValue = AuthorityInfoAccessSyntax
| CertificateTransparency
| Timestamp
| ArchiveRevInfo
| KeyUsage
| NetscapeCertType
| CaVersion
| string;

export class Extension<T = TExtensionValue> extends AsnData<AsnExtension> {
export class Extension<T extends TExtensionValue> extends AsnData<AsnExtension> {
public readonly value: T;

private getAsnExtnValue() {
Expand All @@ -139,95 +142,95 @@ export class Extension<T = TExtensionValue> extends AsnData<AsnExtension> {

switch (this.asn.extnID) {
case id_pe_authorityInfoAccess:
(this.value as any) = AsnParser.parse(asnExtnValue, AuthorityInfoAccessSyntax);
this.value = AsnParser.parse(asnExtnValue, AuthorityInfoAccessSyntax) as T;
break;
case id_ce_authorityKeyIdentifier:
(this.value as any) = AsnParser.parse(asnExtnValue, AuthorityKeyIdentifier);
this.value = AsnParser.parse(asnExtnValue, AuthorityKeyIdentifier) as T;
break;
case id_ce_basicConstraints:
(this.value as any) = AsnParser.parse(asnExtnValue, BasicConstraints);
this.value = AsnParser.parse(asnExtnValue, BasicConstraints) as T;
break;
case id_ce_certificateIssuer:
(this.value as any) = AsnParser.parse(asnExtnValue, CertificateIssuer);
this.value = AsnParser.parse(asnExtnValue, CertificateIssuer) as T;
break;
case id_ce_certificatePolicies:
(this.value as any) = AsnParser.parse(asnExtnValue, CertificatePolicies);
this.value = AsnParser.parse(asnExtnValue, CertificatePolicies) as T;
break;
case id_ce_cRLDistributionPoints:
case '2.5.29.46':
(this.value as any) = AsnParser.parse(asnExtnValue, CRLDistributionPoints);
this.value = AsnParser.parse(asnExtnValue, CRLDistributionPoints) as T;
break;
case id_ce_cRLReasons:
(this.value as any) = AsnParser.parse(asnExtnValue, CRLReason);
this.value = AsnParser.parse(asnExtnValue, CRLReason) as T;
break;
case id_ce_extKeyUsage:
(this.value as any) = AsnParser.parse(asnExtnValue, ExtendedKeyUsage);
this.value = AsnParser.parse(asnExtnValue, ExtendedKeyUsage) as T;
break;
case id_ce_inhibitAnyPolicy:
(this.value as any) = AsnParser.parse(asnExtnValue, InhibitAnyPolicy);
this.value = AsnParser.parse(asnExtnValue, InhibitAnyPolicy) as T;
break;
case id_ce_invalidityDate:
(this.value as any) = AsnParser.parse(asnExtnValue, InvalidityDate);
this.value = AsnParser.parse(asnExtnValue, InvalidityDate) as T;
break;
case id_ce_issuerAltName:
(this.value as any) = AsnParser.parse(asnExtnValue, IssueAlternativeName);
this.value = AsnParser.parse(asnExtnValue, IssueAlternativeName) as T;
break;
case id_ce_keyUsage:
(this.value as any) = AsnParser.parse(asnExtnValue, KeyUsage);
this.value = AsnParser.parse(asnExtnValue, KeyUsage) as T;
break;
case id_ce_nameConstraints:
(this.value as any) = AsnParser.parse(asnExtnValue, NameConstraints);
this.value = AsnParser.parse(asnExtnValue, NameConstraints) as T;
break;
case id_ce_policyConstraints:
(this.value as any) = AsnParser.parse(asnExtnValue, PolicyConstraints);
this.value = AsnParser.parse(asnExtnValue, PolicyConstraints) as T;
break;
case id_ce_policyMappings:
(this.value as any) = AsnParser.parse(asnExtnValue, PolicyMappings);
this.value = AsnParser.parse(asnExtnValue, PolicyMappings) as T;
break;
case id_ce_subjectAltName:
(this.value as any) = AsnParser.parse(asnExtnValue, SubjectAlternativeName);
this.value = AsnParser.parse(asnExtnValue, SubjectAlternativeName) as T;
break;
case id_ce_subjectDirectoryAttributes:
(this.value as any) = AsnParser.parse(asnExtnValue, SubjectDirectoryAttributes);
this.value = AsnParser.parse(asnExtnValue, SubjectDirectoryAttributes) as T;
break;
case id_ce_subjectKeyIdentifier:
(this.value as any) = AsnParser.parse(asnExtnValue, SubjectKeyIdentifier);
this.value = AsnParser.parse(asnExtnValue, SubjectKeyIdentifier) as T;
break;
case id_pe_qcStatements:
(this.value as any) = AsnParser.parse(asnExtnValue, QCStatements);
this.value = AsnParser.parse(asnExtnValue, QCStatements) as T;
break;
case id_certificateTemplate:
(this.value as any) = AsnParser.parse(asnExtnValue, CertificateTemplate);
this.value = AsnParser.parse(asnExtnValue, CertificateTemplate) as T;
break;
case id_enrollCertType:
(this.value as any) = AsnParser.parse(asnExtnValue, EnrollCertTypeChoice);
this.value = AsnParser.parse(asnExtnValue, EnrollCertTypeChoice) as T;
break;
case id_netscapeComment:
(this.value as any) = AsnParser.parse(asnExtnValue, NetscapeComment);
this.value = AsnParser.parse(asnExtnValue, NetscapeComment) as T;
break;
case id_netscapeCertType:
(this.value as any) = AsnParser.parse(asnExtnValue, NetscapeCertType);
this.value = AsnParser.parse(asnExtnValue, NetscapeCertType) as T;
break;
case id_caVersion:
(this.value as any) = AsnParser.parse(asnExtnValue, CaVersion);
this.value = AsnParser.parse(asnExtnValue, CaVersion) as T;
break;
case id_certificateTransparency:
(this.value as any) = AsnParser.parse(asnExtnValue, CertificateTransparency);
this.value = AsnParser.parse(asnExtnValue, CertificateTransparency) as T;
break;
case id_lei:
(this.value as any) = AsnParser.parse(asnExtnValue, LeiChoice);
this.value = AsnParser.parse(asnExtnValue, LeiChoice) as T;
break;
case id_lei_roles:
(this.value as any) = AsnParser.parse(asnExtnValue, LeiRoles);
this.value = AsnParser.parse(asnExtnValue, LeiRoles) as T;
break;
case id_adbe_timestamp:
(this.value as any) = AsnParser.parse(asnExtnValue, Timestamp);
this.value = AsnParser.parse(asnExtnValue, Timestamp) as T;
break;
case id_adbe_archiveRevInfo:
(this.value as any) = AsnParser.parse(asnExtnValue, ArchiveRevInfo);
this.value = AsnParser.parse(asnExtnValue, ArchiveRevInfo) as T;
break;
default:
(this.value as any) = Convert.ToHex(asnExtnValue);
this.value = Convert.ToHex(asnExtnValue) as T;

console.warn('Didn\'t detect parser for extension:', this.asn.extnID);
}
Expand Down
10 changes: 3 additions & 7 deletions src/crypto/x509_certificate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import validator from '../utils/validator';

import { cryptoProvider } from './provider';
import { Name, INameJSON } from './name';
import { Extension } from './extension';
import { Extension, TExtensionValue } from './extension';
import { AsnData } from './asn_data';

export interface ISignature {
Expand All @@ -30,7 +30,7 @@ export class X509Certificate extends AsnData<Certificate> {
public readonly notBefore: Date;
public readonly notAfter: Date;
public readonly validity: string;
public extensions: Extension[];
public extensions: Extension<TExtensionValue>[];
public readonly version: number;
public thumbprints: Record<string, string> = {};

Expand Down Expand Up @@ -171,11 +171,7 @@ export class X509Certificate extends AsnData<Certificate> {
for (let i = 0; i < this.subject.length; i += 1) {
const name = this.subject[i];

if (name.name === 'CN') {
return name.value;
}

if (name.name === 'E') {
if (name.name === 'CN' || name.name === 'E' || name.name === 'O') {
return name.value;
}
}
Expand Down

0 comments on commit ea7432f

Please sign in to comment.