Skip to content

Commit

Permalink
chore(website): add few source examples
Browse files Browse the repository at this point in the history
  • Loading branch information
donskov committed Jan 11, 2024
1 parent 1689504 commit 85ecca0
Show file tree
Hide file tree
Showing 21 changed files with 375 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/TimeStampReq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type TimeStampReqParameters = PkiObjectParameters & Partial<ITimeStampReq
* });
*
* const tspReqRaw = tspReq.toSchema().toBER();
* ```
*/
export class TimeStampReq extends PkiObject implements ITimeStampReq {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

const crypto = pkijs.getCrypto(true);

// Create certificate
const certificate = new pkijs.Certificate();
certificate.version = 2;
certificate.serialNumber = new asn1js.Integer({ value: 1 });
certificate.issuer.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.3", // Common name
value: new asn1js.BmpString({ value: "Test" })
}));
certificate.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.3", // Common name
value: new asn1js.BmpString({ value: "Test" })
}));

certificate.notBefore.value = new Date();
const notAfter = new Date();
notAfter.setUTCFullYear(notAfter.getUTCFullYear() + 1);
certificate.notAfter.value = notAfter;

certificate.extensions = []; // Extensions are not a part of certificate by default, it's an optional array

// "BasicConstraints" extension
const basicConstr = new pkijs.BasicConstraints({
cA: true,
pathLenConstraint: 3
});
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.19",
critical: false,
extnValue: basicConstr.toSchema().toBER(false),
parsedValue: basicConstr // Parsed value for well-known extensions
}));

// "KeyUsage" extension
const bitArray = new ArrayBuffer(1);
const bitView = new Uint8Array(bitArray);
bitView[0] |= 0x02; // Key usage "cRLSign" flag
bitView[0] |= 0x04; // Key usage "keyCertSign" flag
const keyUsage = new asn1js.BitString({ valueHex: bitArray });
certificate.extensions.push(new pkijs.Extension({
extnID: "2.5.29.15",
critical: false,
extnValue: keyUsage.toBER(false),
parsedValue: keyUsage // Parsed value for well-known extensions
}));

const algorithm = pkijs.getAlgorithmParameters("RSASSA-PKCS1-v1_5", "generateKey");
if ("hash" in algorithm.algorithm) {
algorithm.algorithm.hash.name = "SHA-256";
}

const keys = await crypto.generateKey(algorithm.algorithm, true, algorithm.usages);

// Exporting public key into "subjectPublicKeyInfo" value of certificate
await certificate.subjectPublicKeyInfo.importKey(keys.publicKey);

// Signing final certificate
await certificate.sign(keys.privateKey, "SHA-256");

const raw = certificate.toSchema().toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./create-and-validate-certificate.example';

# Create and validate certificate

In this example, you will see how to create a self-signed X.509 certificate, parse an X.509 certificate, and show how to do certificate chain validation engine.

<CodeBlock language="ts">
{source}
</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

// Create OCSP request
const ocspReq = new pkijs.OCSPRequest();

ocspReq.tbsRequest.requestorName = new pkijs.GeneralName({
type: 4,
value: cert.subject,
});

await ocspReq.createForCertificate(cert, {
hashAlgorithm: "SHA-256",
issuerCertificate: issuerCert,
});

const nonce = pkijs.getRandomValues(new Uint8Array(10));
ocspReq.tbsRequest.requestExtensions = [
new pkijs.Extension({
extnID: "1.3.6.1.5.5.7.48.1.2", // nonce
extnValue: new asn1js.OctetString({ valueHex: nonce.buffer }).toBER(),
})
];

// Encode OCSP request
const ocspReqRaw = ocspReq.toSchema(true).toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./working-with-OCSP-requests.example';

# Working with OCSP requests

In this example, you will see how to create and parse OCSP requests.


<CodeBlock language="ts">
{source}
</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

const ocspBasicResp = new pkijs.BasicOCSPResponse();

// Create specific TST info structure to sign
ocspBasicResp.tbsResponseData.responderID = issuerCert.subject;
ocspBasicResp.tbsResponseData.producedAt = new Date();

const certID = new pkijs.CertID();
await certID.createForCertificate(cert, {
hashAlgorithm: "SHA-256",
issuerCertificate: issuerCert,
});
const response = new pkijs.SingleResponse({
certID,
});
response.certStatus = new asn1js.Primitive({
idBlock: {
tagClass: 3, // CONTEXT-SPECIFIC
tagNumber: 0 // [0]
},
lenBlockLength: 1 // The length contains one byte 0x00
}); // status - success
response.thisUpdate = new Date();

ocspBasicResp.tbsResponseData.responses.push(response);

// Add certificates for chain OCSP response validation
ocspBasicResp.certs = [issuerCert];

await ocspBasicResp.sign(keys.privateKey, "SHA-256");

// Finally create completed OCSP response structure
const ocspBasicRespRaw = ocspBasicResp.toSchema().toBER(false);

const ocspResp = new pkijs.OCSPResponse({
responseStatus: new asn1js.Enumerated({ value: 0 }), // success
responseBytes: new pkijs.ResponseBytes({
responseType: pkijs.id_PKIX_OCSP_Basic,
response: new asn1js.OctetString({ valueHex: ocspBasicRespRaw }),
}),
});

const ocspRespRaw = ocspResp.toSchema().toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./working-with-OCSP-responses.example';

# Working with OCSP responses

In this example, you will see how to create and parse OCSP responses.

<CodeBlock language="ts">
{source}
</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

// Get a "crypto" extension
const crypto = pkijs.getCrypto(true);

const pkcs10 = new pkijs.CertificationRequest();

pkcs10.subject.typesAndValues.push(new pkijs.AttributeTypeAndValue({
type: "2.5.4.3",
value: new asn1js.Utf8String({ value: "Test" })
}));

await pkcs10.subjectPublicKeyInfo.importKey(keys.publicKey);

pkcs10.attributes = [];

// Subject Alternative Name
const altNames = new pkijs.GeneralNames({
names: [
new pkijs.GeneralName({ // email
type: 1,
value: "[email protected]"
}),
new pkijs.GeneralName({ // domain
type: 2,
value: "www.domain.com"
}),
]
});

// SubjectKeyIdentifier
const subjectKeyIdentifier = await crypto.digest({ name: "SHA-1" }, pkcs10.subjectPublicKeyInfo.subjectPublicKey.valueBlock.valueHex);

pkcs10.attributes.push(new pkijs.Attribute({
type: "1.2.840.113549.1.9.14", // pkcs-9-at-extensionRequest
values: [(new pkijs.Extensions({
extensions: [
new pkijs.Extension({
extnID: "2.5.29.14", // id-ce-subjectKeyIdentifier
critical: false,
extnValue: (new asn1js.OctetString({ valueHex: subjectKeyIdentifier })).toBER(false)
}),
new pkijs.Extension({
extnID: "2.5.29.17", // id-ce-subjectAltName
critical: false,
extnValue: altNames.toSchema().toBER(false)
}),
new pkijs.Extension({
extnID: "1.2.840.113549.1.9.7", // pkcs-9-at-challengePassword
critical: false,
extnValue: (new asn1js.PrintableString({ value: "passwordChallenge" })).toBER(false)
})
]
})).toSchema()]
}));

// Signing final PKCS#10 request
await pkcs10.sign(keys.privateKey, "SHA-256");

const pkcs10Raw = pkcs10.toSchema(true).toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./working-with-certificate-requests.example';

# Working with certificate requests

In this example, you will see how to create a CSR, parse it and verify its signature.

<CodeBlock language="ts">
{source}
</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

const nonce = pkijs.getRandomValues(new Uint8Array(10)).buffer;

const tspReq = new pkijs.TimeStampReq({
version: 1,
messageImprint: await pkijs.MessageImprint.create("SHA-256", message),
reqPolicy: "1.2.3.4.5.6",
certReq: true,
nonce: new asn1js.Integer({ valueHex: nonce }),
});

const tspReqRaw = tspReq.toSchema().toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./creating-a-timestamp-request.example';

# Creating a Timestamp request

In this example, you will see how to create and parse a timestamp request.

<CodeBlock language="ts">
{source}
</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as pkijs from 'pkijs';
import * as asn1js from 'asn1js';

// Generate random serial number
const serialNumber = pkijs.getRandomValues(new Uint8Array(10)).buffer;

// Create specific TST info structure to sign
const tstInfo = new pkijs.TSTInfo({
version: 1,
policy: tspReq.reqPolicy,
messageImprint: tspReq.messageImprint,
serialNumber: new asn1js.Integer({ valueHex: serialNumber }),
genTime: new Date(),
ordering: true,
accuracy: new pkijs.Accuracy({
seconds: 1,
millis: 1,
micros: 10
}),
nonce: tspReq.nonce,
});

// Create and sign CMS Signed Data with TSTInfo
const cmsSigned = new pkijs.SignedData({
version: 3,
encapContentInfo: new pkijs.EncapsulatedContentInfo({
eContentType: "1.2.840.113549.1.9.16.1.4", // "tSTInfo" content type
eContent: new asn1js.OctetString({ valueHex: tstInfo.toSchema().toBER() }),
}),
signerInfos: [
new pkijs.SignerInfo({
version: 1,
sid: new pkijs.IssuerAndSerialNumber({
issuer: cert.issuer,
serialNumber: cert.serialNumber
})
})
],
certificates: [cert]
});

await cmsSigned.sign(keys.privateKey, 0, "SHA-256");

// Create CMS Content Info
const cmsContent = new pkijs.ContentInfo({
contentType: pkijs.ContentInfo.SIGNED_DATA,
content: cmsSigned.toSchema(true)
});

// Finally create completed TSP response structure
const tspResp = new pkijs.TimeStampResp({
status: new pkijs.PKIStatusInfo({ status: pkijs.PKIStatus.granted }),
timeStampToken: new pkijs.ContentInfo({ schema: cmsContent.toSchema() })
});

const tspRespRaw = tspResp.toSchema().toBER();

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import CodeBlock from '@theme/CodeBlock';
import source from '!!raw-loader!./creating-a-timestamp-response.example';

# Creating a Timestamp response

In this example, you will see how to create, parse and verify timestamp responses.

<CodeBlock language="ts">
{source}
</CodeBlock>
4 changes: 3 additions & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
},
"dependencies": {
"@docusaurus/core": "3.1.0",
"@docusaurus/remark-plugin-npm2yarn": "3.1.0",
"@docusaurus/preset-classic": "3.1.0",
"@docusaurus/remark-plugin-npm2yarn": "3.1.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^1.2.1",
"pkijs": "../",
"prism-react-renderer": "^2.1.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
Expand All @@ -30,6 +31,7 @@
"@docusaurus/types": "3.1.0",
"docusaurus-plugin-sass": "^0.2.5",
"docusaurus-plugin-typedoc": "^0.22.0",
"raw-loader": "^4.0.2",
"sass": "^1.69.5",
"typedoc": "^0.25.3",
"typedoc-plugin-markdown": "^3.17.1",
Expand Down
Loading

0 comments on commit 85ecca0

Please sign in to comment.