Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Get Windows System Root certificates

License

NotificationsYou must be signed in to change notification settings

ukoloff/win-ca

Repository files navigation

Build statusNPM versionStore Roots

Get Windows System Root certificates forNode.js.

Rationale

UnlikeRuby,Node.js on WindowsallowsHTTPS requests out-of-box.But it is implemented in a rather bizarre way:

Node uses astatically compiled, manually updated, hardcoded listof certificate authorities,rather than relying on the system's trust store...Read more

It's somewhat non-intuitive under any OS,but Windows differs from most of themby having its own trust store,fully incompatible withOpenSSL.

This package is intended tofetch Root CAs from Windows' store(Trusted Root Certification Authorities)and make them available toNode.js application with minimal efforts.

Advantages

  • No internet access is required at all
  • Windows store is updated automatically (in most modern environments)
  • Manually installed Root certificates are used
  • Enterprise trusted certificates (GPO etc.) are made available too

Usage

For 95% of users:

  1. Just saynpm install --save win-ca
  2. Then callrequire('win-ca').
  3. That's it!

If you need more -proceed toAPIsection below.

By the way,win-ca is safe to be usedunder other OSes (not M$ Windows).It does nothing there.

Electron

win-ca was adapted to run inside Electron applicationswith no additional configuration(asar supported).

SeeMinimal Electron application using win-cafor usage example.

VS Code extension

Specialextension forVS Codewas created to importwin-cain context of VS Code's Extension Host.

Since all VS Code extensions share the same process,root certificates imported by one of themare immediately available to others.This can allow VS Code extensions to connect to(properly configured)intranet sites from Windows machines.

API

Click to view...

First versions ofwin-caopened Windows'Trusted Root Certificate Store,fetched certificates,deduplicated them and installed tohttps.globalAgent.options.ca,so they are automatically used for allrequests with Node.js'https module.

But sometimes one needs toget these certificates todo something else.For that case,full featured API was devised.It is the only functionwith numerous parametersand operation modes, eg:

constca=require('win-ca')rootCAs=[]// Fetch all certificates in PEM formatca({format:ca.der2.pem,ondata:crt=>rootCAs.push(crt)})

Entry points

win-ca offers three ways of importing:

  1. Regularrequire('win-ca')
  2. Fallbackrequire('win-ca/fallback')
  3. Pure APIrequire('win-ca/api')

They all export the same API,but differ in initialization:

  1. win-cadoes fetch certificates fromRoot store,saves them to diskand makes them available tohttps module with no effort.

  2. win-ca/fallback does the same,but it never usesN-APIfor fetching certificates,so it should workin all versions of Node.jsas well as inside Electron application.

  3. win-ca/api doesnothing,just exports API,so you decide yourselfwhat to do.

API Parameters

API function may be called with no parameters,but that makes little sense.One should pass it object with some fields, ie:

  • formatdefines representation of certificates to fetch.Available values are:

    ConstantValueMeaning
    der2.der0DER-format (binary, Node'sBuffer)
    der2.pem1PEM-format (text, Base64-encoded)
    der2.txt2PEM-format plus some laconic header
    der2.asn13ASN.1-parsed certificate
    der2.x5094Certificate innode-forge format (RSA only!)

    Default value isder.

    See alsoder2 function below.

  • store -which Windows' store to use.Default isRoot(ieTrusted Root Certification Authorities).

    Windows has a whole lot of Certificatestores (egRoot,CA,My,TrustedPublisher etc.)One can list certificates fromany of them(knowing its name)or several stores at once(using array forstore parameter).

    varlist=[]require('win-ca/api')({store:['root','ca'],ondata:list})
  • uniquewhether certificates listshould be deduplicated.Default istrue(no duplicates returned).

    Use{unique: false}to see all certificatesin store.

  • ondata - callback fired for each certificate found.

    Every certificate will be converted toformatand passed as the first (the only) parameter.

    As a syntactic sugar,array can be passed instead of function,it will be populated with certificates.

  • onend - callback fired (with no parameters) at the end of retrieval

    Useful for asynchronous invocations,but works in any case.

  • fallback - boolean flag,indicatingN-APIshouldn't be usedeven if it is available.

    Default value depends on Node.js version(4, 5 and 7{fallback: true};modern versions{fallback: false}).It is alsotrue if Electron is detected.

    Finally, ifwin-ca has been required aswin-ca/fallback,default value for this flag is alsoset totrue.

    Note, that one can forceN-API by setting{fallback: false},but if Node.js cannot proceed,exception will be thrown.It can be catched,but Node.js will nevertheless remain in unstable state,so beware.

  • async - boolean flag to make retrieval process asynchronous(false by default)

    Iftrue, API call returns immediately,certificates will befetched later and feed toondata callback.Finallyonend callback will be called.

  • generator - boolean flag to emulate ES6 generator(default:false)

    If called with this flag,ES6 iterator object is immediatelyreturned(regular or asynchronous -according toasync flag).

    constca=require('win-ca/api')// Iteratefor(letderofca({generator:true})){// Process(der)}// Or thus (Node.js v>=6)letlist=[...ca({generator:true})]// Or even (Node.js v>=10)forawait(letderofca({generator:true,async:true})){// await Process(der)}

    Note, that if callbacks are set alongwithgenerator flag,they will bealso fired.

  • inject - how to install certificates(default:false, ie just fetch from store, do not install)

    If set totrue,certificated fetchedwill be also added tohttps.globalAgent.options.ca(in PEM format, regardless offormat parameter),so all subsequent callstohttps client methods(https.request, https.get etc.)will silently use theminstead of built-in ones.

    If set to'+',newexperimentalmethod is used instead:tls.createSecureContext()is patched andfetched certificatesare usedin addition tobuilt-in ones(and not only forhttps,but for all secure connections).

    Injection mode can be laterchanged (or disabled)with.inject()helper function.

  • save - how to save certificates to disk(default:false, ie useno I/O at all)

    If set to string, or array of strings,they will be treated aslist of candidate folders to save certificates to.First one that exists or can be(recursively) created will be used.

    If no valid folder path found,saving will be silently discarded.

    If{save: true} used,predefined list of folders will be tried:

    • pem folder insidewin-ca module itself
    • .local/win-ca/pem folder inside user's profile

    Certificates will be stored into the folder in two formats:

    • Each certificate as separate text file with special file name(mimics behavour ofOpenSSL'sc_rehash utility) -suitable forSSL_CERT_DIR
    • All certificates in singleroots.pem file -suitable forSSL_CERT_FILE

    Ifwin-ca is required not viawin-ca/api,it calls itself with{inject: true, save: true}and additionaly setsca.path fieldandSSL_CERT_DIR environment variableto the folder with certificates saved.

  • onsave - callback called at the end of saving(ifsave is truthy).

    Path to a folder is passed to callback,or no parameters (undefined)if it has been impossible to save certificates to disk.

Helper functions

Some internal functions are exposed:

der2

varcertificate=ca.der2(format,certificate_in_der_format)

Converts certificate from DERtoformatspecified in first parameter.

Function.der2() is curried:

vartoPEM=ca.der2(ca.der2.pem)varpem=toPEM(der)

hash

varhash=ca.hash(version,certificate_in_der_format)

Gives certificate hash(aka X509_NAME_hash),ie 8-character hexadecimal string,derived from certificate subject.

If version (first parameter) is 0,an old algorithm is used(aka X509_NAME_hash_old, used in OpenSSL v0.*),else - the new one(X509_NAME_hash of OpenSSL v1.*).

Function.hash() is also curried:

varhasher=ca.hash()console.log(hasher(der))

inject

ca.inject(mode)// or:ca.inject(mode,array_of_certificates)

Manages the waycertificates arepassed to other modules.

This function is internally called by APIwhen{inject:} parameter used.

First argument (mode) is injection mode:

  • false: no injection, built-in certificates are used

  • true: put certificates tohttps.globalAgent.options.caand use theminstead of built-in ones forhttps module

  • '+': newexperimental mode:tls.createSecureContext() is patchedand certificates are usedalong with built-in ones.This mode should affect all secure connections,not justhttps module.

Second parameter (array_of_certificates)is list of certificates to inject.If it is omitted,previous list is used(only inject mode is changed).

For example,simplest way to test newinjection mode is:

constca=require('win-ca')// Fetch certificates and start injecting (old way)ca.inject('+')// Switch to new injection mode

Note,that this function should be calledbefore first secure connection is established,since every secure connection populatesdifferent caches,that are extremely hard to invalidate.Changing injection mode in themiddle of secure communicationcan lead to unpredictable results.

exe

Applications that usewin-caare sometimes packed / bundled.In this case one should find appropriateplace for binary utilityroots.exe(used in fallback mode,which is always the case with Electron apps)and then makewin-ca to find the binary.

Function.exe() is intended to provide thisfunctionality.You must call itbefore first invocation of library itself,eg:

varca=require('win-ca/api')ca.exe('/full/path/to/roots.exe')ca({fallback:true,inject:true})

.exe() with no parameters switches todefault location(insidelib folder).In any case it returns previouspath toroots.exe:

console.log(require('win-ca').exe()) // Where is my root.exe?

Legacy API

Click to view...

win-ca v2 had another API,which is preserved for compatibility,but discouraged to use.It consists of three functions:

  • Synchronous:
    • .all()
    • .each()
  • Asynchronous:
    • .each.async()
var ca = require('win-ca')do.something.with(ca.all(ca.der2.pem))

Note:

  1. All three yieldcertificatesinnode-forge's formatby default(unlikemodern API,that returns DERif unspecified by user).

    Unfortunately,node-forge at the time of writing is unable toparse non-RSA certificates(namely, ECC certificates becoming more popular).If yourTrusted Root Certification Authorities storecontains modern certificates,legacy API callswill throw exception.To tackle the problem -pass themformatas the first parameter.

  2. .all() deduplicatescertificates (likeregular API),while both.each callsmay return duplicates({unique: false} applied)

  3. Root store always used(no way forstore: option)

  4. Both.each calls require callback(with optionalformat)

    Synchronous.each() callback gets singleargument - certificate(in specified format)

    varca=require('win-ca')ca.each(ca.der2.x509,crt=>console.log(crt.serialNumber))

    Asynchronous.each.async() callbackgets two parameters:

    • error (which is alwaysundefined in this version)
    • result - certificate in requestedformatorundefined to signal end of retrieval
    letca=require('win-ca')ca.each.async((error,crt)=>{if(error)throwerror;if(crt)console.log(forge.pki.certificateToPem(crt))elseconsole.log("That's all folks!")})

N-API

Current version usesN-API,so it can be used inNode.js versions with N-API support,i.e. v6 and all versions starting from v8.

Thanks to N-API, it is possible to precompileWindows DLL and save it to package,so no compilation is needed at installation time.

For other Node.js versions(v4, 5 or 7)specialfallback utility is calledin the background to fetch the list anyway.

If you wish to use this fallback engine(even for modern Node.js),you can

require('win-ca/fallback')

Caveats

Windows 10 tends tohave only a few certificates initsTrusted Root Certification Authorities storeandlazily add them to it on first use.

If your OS does so,win-ca will still help toconnect to your own sites(protected by self-signed certificates,or by the ones, distributed with GPO),but will make connection towell-known sites(like Google or Twitter) impossible!

The simplest remedy is toonce open desired site inInternet Explorer / Google Chrome(certificate will besilently addedto Root store).

Another option is to switch to newexperimentalinjection method:

require('win-ca').inject('+')

Clearpem folder on publish

If you usewin-ca in some Electron app or VS Code extension,be warned thatnode_modules/win-ca/pem folderishighly likely to be packed into your bundlewith all root certificates on development machine.

You had better remove said folderbefore publishing(eg. inprepack npm script if it applies).

Building

  • npm install
  • npm run pretest
  • npm runnvm$
  • npm publish

This builds bothx86 andx64 versions withN-API support.For older Node.js versions standalone binary utility is built.

See also

Credits

Usesnode-forgeand used to usenode-ffi-napi (ancestor ofnode-ffi).


[8]ページ先頭

©2009-2025 Movatter.jp