Giter VIP home page Giter VIP logo

ocsp's Introduction

OCSP APIs for node.js Build Status

Various OCSP-related APIs to be used with node.js/io.js.

Installing

$ npm install ocsp

Parts

  1. Agent
  2. Cache
  3. Server
  4. check()/verify()
  5. request.generate()
  6. getOCSPURI()

Agent

Usage:

var agent = new ocsp.Agent();

https.request({
  method: ...,
  host: ...,
  port: ...,
  path: ...,
  // Other options

  agent: agent
}, function(res) {
  // ...
});

The following code snippet will perform request to the specified server, and will verify that the certificate of the server using OCSP (either stapling or response from the CA).

NOTE: You may pass options object to new ocsp.Agent(options), it may have following properties:

  • CACacheSize: number of CA certificates to keep in the cache. (Default: 1024)

Cache

Usage:

var cache = new ocsp.Cache();

var server = https.createServer({
  cert: cert,
  key: key
}, function(req, res) {
  res.end('hello world');
});

server.on('OCSPRequest', function(cert, issuer, cb) {
  ocsp.getOCSPURI(cert, function(err, uri) {
    if (err) return cb(err);
    if (uri === null) return cb();

    var req = ocsp.request.generate(cert, issuer);
    cache.probe(req.id, function(err, cached) {
      if (err) return cb(err);
      if (cached !== false) return cb(null, cached.response);

      var options = {
        url: uri,
        ocsp: req.data
      };

      cache.request(req.id, options, cb);
    });
  });
});

Cache should be used to provide OCSP Stapling responses to the client.

NOTE: Constructor accepts options object with following properties:

  • probe: override .probe() method
  • store: override .store() method
  • filter: filter(url, callback) to white list CA urls to do requests

Server

Usage:

var server = ocsp.Server.create({
  cert: cert,
  key: key
});

server.addCert(43, 'good');
server.addCert(44, 'revoked', {
  revocationTime: new Date(),
  revocationReason: 'CACompromise'
});

server.listen(8000);

OCSP Server, i.o.w. HTTP server providing OCSP responses for supplied OCSP requests.

Has following methods:

  • .addCert(serialNumber, status, info), where:
    • serialNumber could be either plain number, or instance of bn.js
    • status is one of good, revoked
    • info should be empty for good and should contain object for revoked (see example above, revocationReason is one of: unspecified, keyCompromise, CACompromise, affiliationChanged, superseded, cessationOfOperation, certificateHold, removeFromCRL, privelegeWithdrawn, AACompromise)
  • All of http.Server methods!

.check()

Usage:

ocsp.check({
  cert: cert,
  issuer: issuerCert
}, function(err, res) {
  if (err)
    throw err;

  console.log(res);
});

Send an OCSP request to the CA and ask if the cert is still valid. res constains the info.

.verify()

Usage:

ocsp.verify({
  request: request,
  // Optional, `issuer: issuerCert,`
  response: response
}, function(err, res) {
});

Verify that response matches the request and is signed by the CA.

request.generate()

Usage:

var req = ocsp.request.generate(cert, issuerCert);

Generate OCSP request for .verify() or for sending it manually to OCSP server.

getOCSPURI()

Usage:

ocsp.getOCSPURI(cert, function(err, uri) {
});

Get URI of OCSP server.

LICENSE

This software is licensed under the MIT License.

Copyright Fedor Indutny, 2015.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ocsp's People

Contributors

bjb568 avatar doublerebel avatar indutny avatar msimerson avatar sebdeckers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

ocsp's Issues

ocsp stapling question

Hi,
I use your ocsp cache.js, how long will the ocsp status I get from OCSP server be cached?
Imaging it will be cached for one day(24h), during this period, if some client(broswer) come to connect my server, my server don't need to connect OCSP server to get ocsp status again. But, I use wireshark and find that my server still go to connect OCSP server. Is it correct?

No support for more advanced signing algorithms

Hi there! When I call ocsp.check on a cert issued by digicert, the OCSP response uses sha384_ecdsa as its signed digest algorithm. This corresponds to 1.2.840.10045.4.3.3.

Error message:

Uncaught Error: Unknown signature algorithm 1,2,840,10045,4,3,3

Are there any plans to support more advanced signing algorithms in OCSP responses?

How to enable ocsp in web socket

I used wb with https and express. Still I get ocsp respond from the ocsp server even I enable ocsp stapling. How to enable it. I coud not figure out it.
This is my code.

var WebSocket = require('ws');
var https = require('https');
var ocsp = require('ocsp');

var bodyparser = require('body-parser');
var express = require('express');
var app = express();

app.use(bodyparser.json());
var PORT = 8080;

var ocspCache = new ocsp.Cache();

var server = new https.createServer({
    cert: fs.readFileSync(`${__dirname}/pki/server/certs/server.cert.pem`),
    key: fs.readFileSync(`${__dirname}/pki/server/private/server.key.pem`),
    ca: [
        fs.readFileSync(`${__dirname}/pki/intermediate/certs/ca-chain.cert.pem`)
    ],
    requestCert: true,
    rejectUnauthorized: true
}, app);

var wss = new WebSocket.Server({
    server
});

wss.on('connection', function connection(ws, req) {

    var cert = req.socket.getPeerCertificate(true);
    var rawCert = cert.raw;
    var rawIssuer = cert.issuerCertificate.raw;

    ocsp.getOCSPURI(rawCert, function(err, uri) {
        if (err) console.log(err);
        var req = ocsp.request.generate(rawCert, rawIssuer);
        var options = {
            url: uri,
            ocsp: req.data
        };
        ocspCache.request(req.id, options, null);
    });

    ws.on('message', function incoming(message) {
        console.log(ocspCache.cache);
        ocsp.check({cert: rawCert, issuer: rawIssuer}, function(err, res) {
            if(err) {
                console.log(err.message);
                ws.send('Failed to obtain OCSP response!');
            } else {
                console.log(res.type);
                var status = res.type;
                if(status == 'good'){
                    console.log('Received: %s', message);
                    ws.send('Hello from server!');
                }else{
                    ws.send('Certificate is revoked!');
                }
            }                              
        });
    });
});

server.listen(PORT, ()=>{
    console.log( (new Date()) + " Server is listening on port " + PORT);
});

@indutny

[Question] Set response property 'revoked' = true instead of throwing error?

I'm using Agent to check whether the target server's certificate has been revoked. If it has been revoked then an error is thrown. Is it possible change this behavior so that it avoids throwing an error and instead sets response.revoked = true?

I need this because even if the certificate has been revoked then I still need the other data from the response.

Also, how can I see whether server is using OCSP stapling or not?

Cache example is write-only

It may makes sense for the example to call .probe() so cached OCSP responses get reused.

var cache = new ocsp.Cache();

var server = https.createServer({
  cert: cert,
  key: key
}, function(req, res) {
  res.end('hello world');
});

server.on('OCSPRequest', function(cert, issuer, cb) {
  ocsp.getOCSPURI(cert, function(err, uri) {
    if (err)
      return cb(err);

    var req = ocsp.request.generate(cert, issuer);
    cache.probe(req.id, function(err, response) {
      if (err)
        return cb(err);

      if (response)
        return cb(null, response);

      var options = {
        url: uri,
        ocsp: req.data
      };

      cache.request(req.id, options, cb);
    });
  });
});

Tests failing

To reproduce

npm test

What should happen

Tests should pass.

What actually happens

Three tests fail.

Relevant output

  3 failing

  1) OCSP Stapling Provider .check() should validate google.com:
     Uncaught Error: Bad OCSP response status: unauthorized
      at Object.parseResponse (lib/ocsp/utils.js:68:11)
      at Object.verify (lib/ocsp/verify.js:52:22)
      at lib/ocsp/check.js:38:12
      at done (lib/ocsp/utils.js:26:7)
      at IncomingMessage.<anonymous> (lib/ocsp/utils.js:46:7)
      at endReadableNT (_stream_readable.js:1204:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:21)

  2) OCSP Cache should cache ocsp response:
     Uncaught TypeError: Cannot read property 'getPeerCertificate' of null
      at Agent.handleOCSPResponse (lib/ocsp/agent.js:70:25)
      at TLSSocket.<anonymous> (lib/ocsp/agent.js:52:17)
      at TLSSocket._finishInit (_tls_wrap.js:916:8)
      at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:686:12)

  3) OCSP Cache "after each" hook:
     Uncaught Error: unsupported certificate purpose
      at TLSSocket.onConnectSecure (_tls_wrap.js:1473:34)
      at TLSSocket._finishInit (_tls_wrap.js:916:8)
      at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:686:12)

Update (2023-07-05):

  • Above results were with Node 12.16.2.
  • With Node 18.16.0, On the first two failures are shown.

Invalid signature leads to process termination

The findResponder() routing in verify.js will throw an exception in case it is unable to verify the signature. This exception is not caught in verify() and thus will lead to crashing of the application.

project/node_modules/ocsp/lib/ocsp/verify.js:25
      throw new Error('Invalid signature');
      ^

Error: Invalid signature
    at findResponder (project/node_modules/ocsp/lib/ocsp/verify.js:25:13)
    at Object.verify (project/eidas-cert-check/node_modules/ocsp/lib/ocsp/verify.js:72:22)
    at project/node_modules/ocsp/lib/ocsp/check.js:38:12
    at done (project/node_modules/ocsp/lib/ocsp/utils.js:26:7)
    at IncomingMessage.<anonymous> (project/node_modules/ocsp/lib/ocsp/utils.js:46:7)
    at IncomingMessage.emit (events.js:327:22)
    at endReadableNT (_stream_readable.js:1224:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)

Getting error in NODE_ENV=production

edit: Just found out that the following errors I get when running ssl without forking ... gonna investigate more. Possibly it is not related to ocsp package at all.


OCSPRequest is getting cert and issuer as null:

server.on('OCSPRequest', function(cert, issuer, cb) {
node_modules/ocsp/lib/ocsp/utils.js:107
var der = raw.toString().match(new RegExp(

TypeError: Cannot read property 'toString' of null
at Object.toDER (/opt/project/src/node_modules/ocsp/lib/ocsp/utils.js:107:16)
at Object.getOCSPURI (/opt/project/src/node_modules/ocsp/lib/ocsp/api.js:10:25)
at Server.<anonymous> (/opt/project/src/node_modules/http-master/src/HttpMasterWor...239:12)
at emitThree (events.js:97:13)
at Server.emit (events.js:175:7)
at requestOCSP (_tls_wrap.js:121:17)
at _tls_wrap.js:165:5
at _tls_wrap.js:104:5
at TLSSocket.sniCallback [as _SNICallback] (/opt/virtkick/src/node_modules/http-mas...:68:22)
at loadSNI (_tls_wrap.js:89:8)

Other error I am getting (linked t othe first one is)

 _tls_wrap.js:172
 self._handle.certCbDone();
 ^
 Error: error:140C6043:SSL routines:SSL_use_certificate:passed a null parameter
 at Error (native)
 at _tls_wrap.js:172:20
 at requestOCSP (_tls_wrap.js:111:12)
 at _tls_wrap.js:165:5
 at _tls_wrap.js:104:5
 at TLSSocket.sniCallback [as _SNICallback] (/opt/project/src/node_modules/http-mas...:68:22)
 at loadSNI (_tls_wrap.js:89:8)
 at TLSSocket.oncertcb (_tls_wrap.js:162:3)
 at _tls_wrap.js:153:18
 at loadSession (_tls_wrap.js:79:5)

Node version is 4.2.2 and latest ocsp.

Cannot read property _getEncoder of undefined when parsing staging letsencrypt certs

Ideas?

Sep 20 23:58:46 dragon node[25459]: [2] [Uncaught exception] TypeError: Cannot read property '_getEncoder' of undefined
Sep 20 23:58:46 dragon node[25459]: at DERNode.use [as _use] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/encoders/der.js:244:16)
Sep 20 23:58:46 dragon node[25459]: at DERNode._getUse (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:431:27)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encodeValue] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:560:21)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encode] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:482:21)
Sep 20 23:58:46 dragon node[25459]: at DERNode.<anonymous> (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:535:23)
Sep 20 23:58:46 dragon node[25459]: at Array.map (native)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encodeValue] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:524:30)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encode] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:482:21)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encodeValue] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:560:48)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encode] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:482:21)
Sep 20 23:58:46 dragon node[25459]: at DERNode.<anonymous> (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:535:23)
Sep 20 23:58:46 dragon node[25459]: at Array.map (native)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encodeValue] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:524:30)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encode] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:482:21)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encodeValue] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:497:30)
Sep 20 23:58:46 dragon node[25459]: at DERNode.encode [as _encode] (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/base/node.js:482:21)
Sep 20 23:58:46 dragon node[25459]: at OCSPRequest.encode (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/encoders/der.js:22:20)
Sep 20 23:58:46 dragon node[25459]: at Entity.encode (/usr/local/node/lib/node_modules/http-master/node_modules/asn1.js/lib/asn1/api.js:60:32)
Sep 20 23:58:46 dragon node[25459]: at Object.generate (/usr/local/node/lib/node_modules/http-master/node_modules/ocsp/lib/ocsp/request.js:63:31)
Sep 20 23:58:46 dragon node[25459]: at /usr/local/node/lib/node_modules/http-master/src/HttpMasterWorker.js:258:32
Sep 20 23:58:46 dragon node[25459]: at Object.getAuthorityInfo (/usr/local/node/lib/node_modules/http-master/node_modules/ocsp/lib/ocsp/utils.js:168:10)
Sep 20 23:58:46 dragon node[25459]: at Object.getOCSPURI (/usr/local/node/lib/node_modules/http-master/node_modules/ocsp/lib/ocsp/api.js:13:14)
Sep 20 23:58:46 dragon node[25459]: at Server.<anonymous> (/usr/local/node/lib/node_modules/http-master/src/HttpMasterWorker.js:250:12)
Sep 20 23:58:46 dragon node[25459]: at emitThree (events.js:116:13)
Sep 20 23:58:46 dragon node[25459]: at Server.emit (events.js:194:7)
Sep 20 23:58:46 dragon node[25459]: at Server.emit (/usr/local/node/lib/node_modules/http-master/node_modules/spdy/lib/spdy/server.js:218:40)
Sep 20 23:58:46 dragon node[25459]: at requestOCSP (_tls_wrap.js:123:17)

Cert and Nonce Missing from OCSP Response?

I've only been able to test this partially.
I see from openssl's ocsp test tool used something like this.

openssl ocsp -issuer CA_pem.crt -cert server-pem.crt -text -url http://some.domain.server/

That an error about missing the nonce appears.

WARNING: no nonce in response
Response Verify Failure

I think there is something else not working in my initial attempts maybe wrong cert or because of chaining etc. so it might evaporate but the initial WARNING is about missing the nonce

It is an Extended Response concept, seen in the test tools initial request output

Request Extensions:
        OCSP Nonce:
              04E900581CE39516????....?????945FF2CD43DD160

I searched this codebase for nonce and got nothing except in the request generator.
all I can find is this TODO that mentions Extensions might be missing from the response still!?

TODO(indutny): send extensions

error from ocsp agent

/home/noms/spoop2/server/node_modules/ocsp/lib/ocsp/agent.js:70
var cert = socket.ssl.getPeerCertificate(true);
^

TypeError: Cannot read property 'getPeerCertificate' of null
at Agent.handleOCSPResponse (/home/noms/spoop2/server/node_modules/ocsp/lib/ocsp/agent.js:70:25)
at TLSSocket. (/home/noms/spoop2/server/node_modules/ocsp/lib/ocsp/agent.js:52:17)
at TLSSocket.emit (events.js:202:15)
at TLSSocket._finishInit (_tls_wrap.js:631:8)

ocsp.check() ends with 'Error: Invalid signature'

hello,

i read some of the issues about 'invalid signatures' in this repository and couldn't relate my problem with one of them. maybe i misread something or so. well, i wrote the following piece of code (running snippet):

const express = require('express');
const fs = require('fs');
const https = require('https');
const path = require('path');
const app = express();
const ocsp = require("ocsp");

const opts = {
        key: fs.readFileSync(path.join(__dirname, '../CA/server/server_key.pem')),
        cert: fs.readFileSync(path.join(__dirname, '../CA/server/server_cert.pem')),
        ca: [ fs.readFileSync(path.join(__dirname, '../CA/cacert.pem')) ],
        requestCert: true,
        rejectUnauthorized: false,
};

var server = https.createServer(opts, app);
server.on("secureConnection", function (sock) {
        const cert = sock.getPeerCertificate(true);
        const rawCert = cert.raw;
        const rawIssuer = cert.issuerCertificate.raw;
        console.log(rawCert);
        console.log(rawIssuer);
        ocsp.check({cert: rawCert, issuer: rawIssuer}, function(err, res) {
                if(err) {
                        console.dir(err);
                } else {
                        console.dir(res);                         
                }                                    
        });                              
});                                                                        
                                                                           
server.listen(443, () => {               
        console.log(`SERVER ONLINE at https://0.0.0.0:443`);
});         

this little program opens a https socket and on a secured connection it gets the client certificate via sock.getPeerCertificate(). with ocsp.check() and the derived raw certs of client and issuer i run into this error.

SERVER ONLINE at https://0.0.0.0:443
<Buffer 30 82 05 6d 30 82 03 55 a0 03 02 01 02 02 01 03 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 81 a9 31 0b 30 09 06 03 55 04 06 13 02 44 45 31 0f 30 ... >
<Buffer 30 82 06 6c 30 82 04 54 a0 03 02 01 02 02 14 37 1f 82 b9 7e 71 db c4 99 7c d3 aa 7e 7a b8 c4 ef 56 7b 29 30 0d 06 09 2a 86 48 86 f7 0d 01 01 05 05 00 ... >
Error: Invalid signature
    at Object.verify (/opt/secureclient/node_modules/ocsp/lib/ocsp/verify.js:81:17)
    at /opt/secureclient/node_modules/ocsp/lib/ocsp/check.js:38:12
    at done (/opt/secureclient/node_modules/ocsp/lib/ocsp/utils.js:26:7)
    at IncomingMessage.<anonymous> (/opt/secureclient/node_modules/ocsp/lib/ocsp/utils.js:46:7)
    at IncomingMessage.emit (events.js:194:15)
    at endReadableNT (_stream_readable.js:1103:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

the ocsp server is the plain openssl ocsp server, which get launched like this:
openssl ocsp -index index.txt -port 8888 -rsigner server/signer.pem -CA cacert.pem -text -out log.txt

what signature is checked in verify.js line 81? and how can i get it work? do you need any further information?

OCSP check failed against windows blob storage

I am using ocsp 1.2.0 and latest of asn1.js-rfc5280. However, ocsp check failed with error Invalid signauture when checking against azure blob storage(while it succeed for amazons s3). So I am wondering what is wrong, and also, is there anyway to turn on logging to further troubleshooting the issue.

I wrote a simple javascript to reproduce the issue. Note, check failed on windows.net, but succeed for s3 endpoint.

const tls = require('tls');
const ocsp = require('ocsp');
const rfc5280 = require('asn1.js-rfc5280');

const options = {
  host: "2srsfctest1stage000.blob.core.windows.net",
  //host: "s3-eu-west-1.amazonaws.com",
  port: 443
};

const socket = tls.connect(8000, options, function(){
  cert = socket.getPeerCertificate(true);
  var issuer = cert.issuerCertificate;
  cert = cert.raw;
  try {
    cert = rfc5280.Certificate.decode(cert, 'der');

    if (issuer) {
      issuer = issuer.raw;
      issuer = rfc5280.Certificate.decode(issuer, 'der');
    }
  } catch (e) {
    console.log(e);
  }

  ocsp.check({
    cert: cert,
    issuer: issuer
  }, function(err, res){
    if (err)
    {
      console.log(err);
    }

    if (res)
    {
      console.log(res);
    }
  })
});

Check() through a proxy?

I'm trying to use ocsp in a package that also consumes https-proxy-agent to allow connections through a proxy.

While I can't compose 2 agents, I can get the underlying socket and it's certificate but need to contact the OCSP server through the same proxy.

Can Check() take another member in its options parameter that would be passed to the http.request to allow an agent to be specified?

Would be happy to send a PR, or look at an alternate solution.

Responses from OpenCA's OCSPd supported?

Hello.. thanks for this module, it's definitely needed.

When testing check() with a good cert against OCSPd (from the OpenCA project), it's throwing "Invalid signature."

OCSPd logs:

Aug  6 13:53:49 watchtower ocspd[9710]: Request for certificate serial 4096
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:684] [DEBUG] CRL::CA [ca-ec-sockets] nameHash OK
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:699] [DEBUG] CRL::CA [ca-ec-sockets] issuerKeyHash OK
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:324] [DEBUG] Using the specific token for the found CA (ca-ec-sockets)
Aug  6 13:53:49 watchtower ocspd[9710]: valid certificate status [serial 4096]
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:84] [DEBUG] Digest Algorithm For Signature: SHA1
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:97] [DEBUG] Signing Certificate:
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:98] [DEBUG] - Serial .....: 4100
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:99] [DEBUG] - Subject ....: C=US, ST=Nevada, L=Las Vegas, O=MyCompany Inc., CN=ocsp-sockets.mycompany.com
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:100] [DEBUG] - Issuer .....: C=US, ST=Nevada, L=Las Vegas, O=MyCompany Inc., CN=MyCompany Sockets Root CA
Aug  6 13:53:49 watchtower ocspd[9710]: [hsm_main.c:648] [DEBUG] Signature Size (512 bytes)
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:119] [DEBUG] Response signed successfully
Aug  6 13:53:49 watchtower ocspd[9710]: [response.c:622] [DEBUG] OCSP Response Bytes = 2333, HTTP Header Bytes = 184

When trying to trace through your verification code I noticed:

// TODO(indutny): support other responders

So I was just curious if there might be a known issue with OSCPd before digging further.

Thanks!

Bad decrypt.

I am using OCSP server with key and cert of CA.
And trying to get response from it using ocsp.cache with webserver keypair. But the OCSP server is crashing with error.

  var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength);
                         ^
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

The error is occuring at: https://github.com/indutny/ocsp/blob/master/lib/ocsp/server.js#L141

I know main problem here is the crypto material, wrong material must have resulted in this behaviour. Let me know if certificates and keys are required.

OCSP Cache timeout error

Thank you for this node module.

catch a exception, when the cache's timeout been trigged,

Worker 144574 catch uncaughtException!!!
[TypeError: Cannot convert undefined or null to object]
TypeError: Cannot convert undefined or null to object
    at null._onTimeout (/data/system/ws_cluster/node_modules/ocsp/lib/ocsp/cache.js:36:25)
    at Timer.listOnTimeout (timers.js:92:15)

I found this code:

Cache.prototype.store = function store(id, response, maxTime, callback) {
  if (this.cache.hasOwnProperty(id))
    clearTimeout(this.cache[id].timer);
  this.cache[id] = {
    response: response,
    timer: setTimeout(function() {
      delete this.cache[id];
    }, maxTime)
  };

  callback(null, null);
};

I think, the scope of this.cache[id] is error?

fix this it,

Cache.prototype.store = function store(id, response, maxTime, callback) {
  if (this.cache.hasOwnProperty(id))
    clearTimeout(this.cache[id].timer);

  var self = this;
  this.cache[id] = {
    response: response,
    timer: setTimeout(function() {
      delete self.cache[id];
    }, maxTime)
  };

  callback(null, null);
};

Is it OK?

How to enable ocsp?

Sorry, noob here. I made a test on ssllabs.com and this says "OCSP stapling No"

What do i need to make it pass? Cache? Server? I don't fully understand what ssllabs tests here

Why is this verification failing?

Thanks for putting this module together!
I cannot figure out why validation is failing for my host www.muuuf.de. Specifically, this is failing

const https = require("https")
const ocsp = require("ocsp")
const agent = new ocsp.Agent()

https.request({
  host: "www.muuuf.de",
  agent: agent
}, function(res) {
});

even though this

openssl s_client -connect www.muuuf.de:443 -servername www.muuuf.de -status

produces output that looks valid and verified to me:

OCSP response: 
======================================
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
    Produced At: May 19 16:59:00 2016 GMT
    Responses:
    Certificate ID:
      Hash Algorithm: sha1
      Issuer Name Hash: 7EE66AE7729AB3FCF8A220646C16A12D6071085D
      Issuer Key Hash: A84A6A63047DDDBAE6D139B7A64565EFF3A8ECA1
      Serial Number: 03677DA61C6153D2591BC59B1B6DE59F527B
    Cert Status: good
    This Update: May 19 16:00:00 2016 GMT
    Next Update: May 26 16:00:00 2016 GMT

Verification failure on many popular sites

Hi @indutny, this lib is great, but I'm having lots of trouble verifying OCSP on some popular sites. I was wondering if you had any idea what is different between the cert setup in the success cases versus the failure cases of this simple script:

'use strict';

const ocsp = require('ocsp');
const https = require('https');

const agent = new ocsp.Agent();

function go(host) {
  const req = https.request({host: host, agent: agent}, (res) => {
    console.log(host, res.statusCode);
  });
  req.on('error', (error) => {
    console.error(host, error);
  });
  req.end();
}

go('google.com');
go('yahoo.com');
go('nytimes.com');
go('microsoft.com');

Running this script produces the following:

$ node ocsp.js 
nytimes.com 301
yahoo.com Error: Invalid signature
    at Object.verify (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/verify.js:50:17)
    at onIssuer (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:93:12)
    at Agent.handleOCSPResponse (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:103:12)
    at TLSSocket.<anonymous> (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:52:17)
    at emitNone (events.js:91:20)
    at TLSSocket.emit (events.js:185:7)
    at TLSSocket._finishInit (_tls_wrap.js:603:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:433:38)
microsoft.com Error: Invalid signature
    at Object.verify (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/verify.js:50:17)
    at onIssuer (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:93:12)
    at Agent.handleOCSPResponse (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:103:12)
    at TLSSocket.<anonymous> (/Users/bent/src/test/node_modules/ocsp/lib/ocsp/agent.js:52:17)
    at emitNone (events.js:91:20)
    at TLSSocket.emit (events.js:185:7)
    at TLSSocket._finishInit (_tls_wrap.js:603:8)
    at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:433:38)
google.com 301

Example should handle null uri which happens when OCSP server is down

Just encountered it in production.when letsencrypte did some maintenance work on their infrastructure taking down their OCSP servers for a couple minutes.

Example should handle this case. Note the if(uri === null)

    server.on('OCSPRequest', function(cert, issuer, cb) {
      ocsp.getOCSPURI(cert, function(err, uri) {
        if (err) {
          return cb(err);
        }
        if(uri === null) {
          // handle not working OCSP server
          return cb();
        }
        var req = ocsp.request.generate(cert, issuer);
        var options = {
          url: uri,
          ocsp: req.data
        };
        cache.request(req.id, options, cb);
      });
    });

Also maybe it should be somehow handled automatically by the ocsp library?

Test failing in .check()

Was trying to run the tests before implementing a change but failed out of the box.

npm t

> [email protected] test /Users/seb/Code/sebdeckers/ocsp
> mocha test/*-test.js



  OCSP Agent
    ✓ should connect and validate www.google.com (122ms)
    ✓ should connect and validate google.com (141ms)
    ✓ should connect and validate helloworld.letsencrypt.org (724ms)
    ✓ should connect and validate yahoo.com (908ms)
    ✓ should connect and validate nytimes.com (727ms)
    ✓ should connect and validate microsoft.com (1112ms)

  OCSP Stapling Provider
    .check()
      1) should validate google.com
    .verify()
      ✓ should verify reddit.com's stapling (377ms)
    .getOCSPURI()
      ✓ should work on cert without extensions

  OCSP Cache
    ✓ should cache ocsp response (50ms)

  OCSP Server
    ✓ should provide ocsp response to the client (46ms)


  10 passing (4s)
  1 failing

  1) OCSP Stapling Provider .check() should validate google.com:
     Uncaught Error: Failed to obtain OCSP response: 404
      at ClientRequest.onResponse (lib/ocsp/utils.js:33:9)
      at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:550:21)
      at HTTPParser.parserOnHeadersComplete (_http_common.js:117:23)
      at Socket.socketOnData (_http_client.js:439:20)
      at addChunk (_stream_readable.js:265:12)
      at readableAddChunk (_stream_readable.js:252:11)
      at Socket.Readable.push (_stream_readable.js:209:10)
      at TCP.onread (net.js:598:20)



npm ERR! Test failed.  See above for more details.

OCSP cache doesn’t have a means of clearing all cache invalidation check intervals

Use case

While running unit tests that use the OCSP cache, the Node process does not exits due to active handles (the cache expiry intervals)

Suggested fix

Add a method that clears the cache and cache expiry interval checks. e.g.,

Cache.prototype.clear = function clear() {
  var cacheIds = Object.keys(this.cache);
  cacheIds.forEach(function (cacheId) {
    clearInterval(this.cache[cacheId].timer);
  })
  this.cache.length = 0;
};

Workaround

In your app, clear the intervals manually. e.g., in my app:

const ocspCache = new ocsp.Cache()
// …
const cacheIds = Object.keys(ocspCache.cache)
cacheIds.forEach(cacheId => {
  clearInterval(ocspCache.cache[cacheId].timer)
})

plan for send certs?

hello.
This project is awesome to implement some thing about ocsp:)
@indutny do you have plan to complete your send certs? for ocsp response.
now we do not send certs on ocsp response, so always get the output when using openssl to test as following:

routines:OCSP_basic_verify:signer certificate not found.

never mind, now it's enough good even if do not send certs:)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.