Sample code for 30+ languages & platforms
Dart Requires Chilkat v11.0.0+

Generate a CSR with keyUsage, extKeyUsage, and other Extensions

See more CSR Examples

Demonstrates how to generate a CSR containing a 1.2.840.113549.1.9.14 extensionRequest with the following extensions:
  • 1.3.6.1.4.1.311.20.2 enrollCerttypeExtension
  • 2.5.29.15 keyUsage
  • 2.5.29.37 extKeyUsage
  • 2.5.29.14 subjectKeyIdentifier

Chilkat Dart Downloads

Dart
import 'package:chilkat/chilkat.dart';

void main() {
  // This requires the Chilkat API to have been previously unlocked.
  // See Global Unlock Sample for sample code.

  // This example will generate a secp256r1 ECDSA key for the CSR.
  final ecc = CkEcc();
  final prng = CkPrng();
  final privKey = CkPrivateKey();
  try {
    ecc.genKey('secp256r1', prng, privKey);
  } on ChilkatException {
    print('Failed to generate a new ECDSA private key.');
    return;
  }

  final csr = CkCsr();

  // Add common CSR fields:
  csr.commonName = 'mysubdomain.mydomain.com';
  csr.country = 'GB';
  csr.state = 'Yorks';
  csr.locality = 'York';
  csr.company = 'Internet Widgits Pty Ltd';
  csr.emailAddress = 'support@mydomain.com';

  // Add the following 1.2.840.113549.1.9.14 extensionRequest
  // Note: The easiest way to know the content and format of the XML to be added is to examine
  // a pre-existing CSR with the same desired extensionRequest.  You can use Chilkat to
  // get the extensionRequest from an existing CSR. 

  // Here is a sample extension request:

  // <?xml version="1.0" encoding="utf-8"?>
  // <set>
  //     <sequence>
  //         <sequence>
  //             <oid>1.3.6.1.4.1.311.20.2</oid>
  //             <asnOctets>
  //                 <universal tag="30" constructed="0">AEUAbgBkAEUAbgB0AGkAdAB5AEMAbABpAGUAbgB0AEEAdQB0AGgAQwBlAHIAdABpAGYAaQBjAGEAdABl
  // AF8AQwBTAFIAUABhAHMAcwB0AGgAcgBvAHUAZwBoAC8AVgAx</universal>
  //             </asnOctets>
  //         </sequence>
  //         <sequence>
  //             <oid>2.5.29.15</oid>
  //             <bool>1</bool>
  //             <asnOctets>
  //                 <bits n="3">A0</bits>
  //             </asnOctets>
  //         </sequence>
  //         <sequence>
  //             <oid>2.5.29.37</oid>
  //             <asnOctets>
  //                 <sequence>
  //                     <oid>1.3.6.1.5.5.7.3.3</oid>
  //                 </sequence>
  //             </asnOctets>
  //         </sequence>
  //         <sequence>
  //             <oid>2.5.29.14</oid>
  //             <asnOctets>
  //                 <octets>MCzBMQAViXBz8IDt8LsgmJxJ4Xg=</octets>
  //             </asnOctets>
  //         </sequence>
  //     </sequence>
  // </set>

  // Use this online tool to generate code from sample XML: 
  // Generate Code to Create XML

  // A few notes:
  // The string "AEUAbgBkAEUAbgB0AGkAdAB5AEMAbABpAGUAbgB0AEEAdQB0AGgAQwBlAHIAdABpAGYAaQBjAGEAdABlAF8AQwBTAFIAUABhAHMAcwB0AGgAcgBvAHUAZwBoAC8AVgAx"
  // is the base64 encoding of the utf-16be byte representation of the string "EndEntityClientAuthCertificate_CSRPassthrough/V1"

  final s = 'EndEntityClientAuthCertificate_CSRPassthrough/V1';
  final bdTemp = CkBinData();
  bdTemp.appendString(s, 'utf-16be');
  final sBase64Utf16be = bdTemp.getEncoded('base64');
  // The string should be "AEUA....."
  print(sBase64Utf16be);

  // Here's the code to generate the above extension request.

  final xml = CkXml();
  xml.tag = 'set';
  xml.updateChildContent('sequence|sequence|oid', '1.3.6.1.4.1.311.20.2');
  xml.updateAttrAt('sequence|sequence|asnOctets|universal', true, 'tag', '30');
  xml.updateAttrAt('sequence|sequence|asnOctets|universal', true, 'constructed', '0');
  xml.updateChildContent('sequence|sequence|asnOctets|universal', sBase64Utf16be);
  xml.updateChildContent('sequence|sequence[1]|oid', '2.5.29.15');
  xml.updateChildContent('sequence|sequence[1]|bool', '1');
  xml.updateAttrAt('sequence|sequence[1]|asnOctets|bits', true, 'n', '3');
  // A0 is hex for decimal 160.
  xml.updateChildContent('sequence|sequence[1]|asnOctets|bits', 'A0');
  xml.updateChildContent('sequence|sequence[2]|oid', '2.5.29.37');
  xml.updateChildContent('sequence|sequence[2]|asnOctets|sequence|oid', '1.3.6.1.5.5.7.3.3');

  // This is the subjectKeyIdentifier extension.
  // The string "MCzBMQAViXBz8IDt8LsgmJxJ4Xg=" is base64 that decodes to 20 bytes, which is a SHA1 hash.
  // This is simply a hash of the DER of the public key.

  final pubKey = CkPublicKey();
  privKey.toPublicKey(pubKey);
  final bdPubKeyDer = CkBinData();
  bdPubKeyDer.appendEncoded(pubKey.getEncoded(true, 'base64'), 'base64');
  final ski = bdPubKeyDer.getHash('sha1', 'base64');

  xml.updateChildContent('sequence|sequence[3]|oid', '2.5.29.14');
  xml.updateChildContent('sequence|sequence[3]|asnOctets|octets', ski);

  // Add the extension request to the CSR
  csr.setExtensionRequest(xml);

  // Generate the CSR with the extension request
  final String csrPem;
  try {
    csrPem = csr.genCsrPem(privKey);
  } on ChilkatException catch (e) {
    print(e.lastErrorText);
    return;
  }

  print(csrPem);
}