it("should explore a 2048 bits RSA certificate", function () {
        var certificate = crypto_utils.readCertificate(path.join(__dirname, "../fixtures/certs/server_cert_2048.pem"));
        var data = crypto_utils.exploreCertificate(certificate);
        data.publicKeyLength.should.eql(256);
        data.notAfter.should.be.instanceOf(Date);
        data.notBefore.should.be.instanceOf(Date);

    });
Esempio n. 2
0
function asymmetricVerifyChunk(chunk, certificate) {

    var crypto_factory = this;
    assert(chunk instanceof Buffer);
    assert(certificate instanceof Buffer);
    // let's get the signatureLength by checking the size
    // of the certificate's public key
    var cert = crypto_utils.exploreCertificate(certificate);

    var signatureLength = cert.publicKeyLength; // 1024 bits = 128Bytes or 2048=256Bytes
    var block_to_verify = chunk.slice(0, chunk.length - signatureLength);
    var signature = chunk.slice(chunk.length - signatureLength);
    return crypto_factory.asymmetricVerify(block_to_verify, signature, certificate);

}
// Bad_CertificateHostNameInvalid            The HostName used to connect to a Server does not match a HostName in the
//                                           Certificate.
// Bad_CertificateIssuerRevocationUnknown    It was not possible to determine if the Issuer Certificate has been revoked.
// Bad_CertificateIssuerUseNotAllowed        The Issuer Certificate may not be used for the requested operation.
// Bad_CertificateIssuerTimeInvalid          An Issuer Certificate has expired or is not yet valid.
// Bad_CertificateIssuerRevoked              The Issuer Certificate has been revoked.
// Bad_CertificateInvalid                    The certificate provided as a parameter is not valid.
// Bad_CertificateRevocationUnknown          It was not possible to determine if the Certificate has been revoked.
// Bad_CertificateRevoked                    The Certificate has been revoked.
// Bad_CertificateTimeInvalid                The Certificate has expired or is not yet valid.
// Bad_CertificateUriInvalid                 The URI specified in the ApplicationDescription does not match the URI in the Certificate.
// Bad_CertificateUntrusted                  The Certificate is not trusted.
// Bad_CertificateUseNotAllowed              The Certificate may not be used for the requested operation.

// also see OPCUA 1.02 part 4 :
//  - page 95  6.1.3 Determining if a Certificate is Trusted
// -  page 100 6.2.3 Validating a Software Certificate
//
function _check_certificate_validity(certificate) {

    // Is the  signature on the SoftwareCertificate valid .?
    if (!certificate) {
        // missing certificate
        return StatusCodes.BadSecurityChecksFailed;
    }

    //-- var split_der = require("lib/misc/crypto_explore_certificate").split_der;
    //-- var chain = split_der(securityHeader.senderCertificate);
    //-- //xx console.log("xxx NB CERTIFICATE IN CHAIN = ".red,chain.length);

    // Has SoftwareCertificate passed its issue date and has it not expired ?
    // check dates
    var cert = crypto_utils.exploreCertificate(certificate);

    var now = new Date();

    if ( cert.notBefore.getTime() > now.getTime() ) {
        // certificate is not active yet
        console.log(" Sender certificate is invalid : certificate is not active yet !".red + "  not before date =" + cert.notBefore);
        return StatusCodes.BadCertificateIssuerTimeInvalid;
    }
    if (cert.notAfter.getTime() <= now.getTime() ) {
        // certificate is obsolete
        console.log(" Sender certificate is invalid : certificate has expired !".red + " not after date =" + cert.notAfter);
        return StatusCodes.BadCertificateIssuerTimeInvalid;
    }

    // Has SoftwareCertificate has  been revoked by the issuer ?
    // TODO: check if certificate is revoked or not ...
    // StatusCodes.BadCertificateRevoked

    // is issuer Certificate  valid and has not been revoked by the CA that issued it. ?
    // TODO : check validity of issuer certificate
    // StatusCodes.BadCertificateIssuerRevoked

    //does the URI specified in the ApplicationDescription  match the URI in the Certificate ?
    // TODO : check ApplicationDescription of issuer certificate
    // return StatusCodes.BadCertificateUriInvalid

    return StatusCodes.Good;
}
MessageBuilder.prototype._decrypt_OPN = function (binaryStream) {

    assert(this.securityPolicy !== SecurityPolicy.None);
    assert(this.securityPolicy !== SecurityPolicy.Invalid);
    assert(this.securityMode !== MessageSecurityMode.NONE);
    //xx assert(this.securityMode !== MessageSecurityMode.INVALID);

    /* istanbul ignore next */
    if (doDebug) {
        debugLog("securityHeader", JSON.stringify(this.securityHeader, null, " "));
    }

    // OpcUA part 2 V 1.02 page 15
    // 4.11 OPC UA Security Related Services
    // [...]
    // The OPC UA Client sends its Public Key in a Digital Certificate and secret information with the
    // OpenSecureChannel service Message to the Server. This Message is secured by applying
    // Asymmetric Encryption with the Server's Public Key and by generating Asymmetric Signatures with
    // the Client's Private Key. However the Digital Certificate is sent unencrypted so that the receiver can
    // use it to verify the Asymmetric Signature.
    // [...]
    //

    /* istanbul ignore next */
    if (doDebug) {
        debugLog("EN------------------------------".cyan);
        debugLog(hexDump(binaryStream._buffer));
        debugLog("---------------------- SENDER CERTIFICATE");
        debugLog(hexDump(this.securityHeader.senderCertificate));
    }

    /* istanbul ignore next */
    if (!crypto_utils.isFullySupported()) {
        this._report_error("YOUR NODE CONFIGURATION DOES NOT ALLOW SIGN and ENCRYPT YET - ");
        return false;
    }

    if (!this.cryptoFactory) {
        this._report_error(" Security Policy " + this.securityPolicy.key + " is not implemented yet");
        return false;
    }

    // The message has been signed  with sender private key and has been encrypted with receiver public key.
    // We shall decrypt it with the receiver private key.
    var buf = binaryStream._buffer.slice(binaryStream.length);

    if (this.securityHeader.receiverCertificateThumbprint) { // this mean that the message has been encrypted ....

        assert(typeof this.privateKey === "string", "expecting valid key");

        var decryptedBuffer = this.cryptoFactory.asymmetricDecrypt(buf, this.privateKey);

        // replace decrypted buffer in initial buffer
        decryptedBuffer.copy(binaryStream._buffer, binaryStream.length);

        // adjust length
        binaryStream._buffer = binaryStream._buffer.slice(0, binaryStream.length + decryptedBuffer.length);

        /* istanbul ignore next */
        if (doDebug) {
            debugLog("DE-----------------------------".cyan);
            debugLog(hexDump(binaryStream._buffer));
            debugLog("-------------------------------".cyan);
            debugLog("Certificate :", hexDump(this.securityHeader.senderCertificate));
        }
    }

    var cert = crypto_utils.exploreCertificate(this.securityHeader.senderCertificate);
    // then verify the signature
    var signatureLength = cert.publicKeyLength; // 1024 bits = 128Bytes or 2048=256Bytes
    assert(signatureLength === 128 || signatureLength === 256);

    var chunk = binaryStream._buffer;

    var signatureIsOK = this.cryptoFactory.asymmetricVerifyChunk(chunk, this.securityHeader.senderCertificate);

    if (!signatureIsOK) {
        console.log(hexDump(binaryStream._buffer));
        this._report_error("SIGN and ENCRYPT asymmetricVerify : Invalid packet signature");
        return false;
    }

    // remove signature
    binaryStream._buffer = crypto_utils.reduceLength(binaryStream._buffer, signatureLength);

    // remove padding
    if (this.securityHeader.receiverCertificateThumbprint) {
        binaryStream._buffer = crypto_utils.removePadding(binaryStream._buffer);
    }

    return true; // success
};
ServerSecureChannelLayer.prototype.getSignatureLength = function() {

    var self = this;
    var cert = crypto_utils.exploreCertificate(self.getCertificate());
    return cert.publicKeyLength; // 1024 bits = 128Bytes or 2048=256Bytes
};