Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
switch (request.securityMode) {
case MessageSecurityMode.None:
securityHeader = new AsymmetricAlgorithmSecurityHeader({
receiverCertificateThumbprint: null, // message not encrypted
securityPolicyUri: "http://opcfoundation.org/UA/SecurityPolicy#None",
senderCertificate: null // message not signed
});
break;
case MessageSecurityMode.Sign:
case MessageSecurityMode.SignAndEncrypt:
default: {
// get the thumbprint of the client certificate
const thumbprint = this.receiverCertificate
? makeSHA1Thumbprint(this.receiverCertificate)
: null;
if (!this.clientSecurityHeader) {
throw new Error("Internal");
}
const asymmClientSecurityHeader = this.clientSecurityHeader as AsymmetricAlgorithmSecurityHeader;
securityHeader = new AsymmetricAlgorithmSecurityHeader({
receiverCertificateThumbprint: thumbprint, // message not encrypted (????)
securityPolicyUri: asymmClientSecurityHeader.securityPolicyUri,
senderCertificate: this.getCertificateChain() // certificate of the private key used to sign the message
});
}
}
return securityHeader;
}
private _check_receiverCertificateThumbprint(clientSecurityHeader: SecurityHeader): boolean {
if (clientSecurityHeader instanceof SymmetricAlgorithmSecurityHeader) {
return false;
}
if (clientSecurityHeader.receiverCertificateThumbprint) {
// check if the receiverCertificateThumbprint is my certificate thumbprint
const serverCertificateChain = this.getCertificateChain();
const myCertificateThumbPrint = makeSHA1Thumbprint(serverCertificateChain);
const thisIsMyCertificate =
myCertificateThumbPrint.toString("hex") ===
clientSecurityHeader.receiverCertificateThumbprint.toString("hex");
if (doDebug && !thisIsMyCertificate) {
debugLog("receiverCertificateThumbprint do not match server certificate",
myCertificateThumbPrint.toString("hex") + " <> "
+ clientSecurityHeader.receiverCertificateThumbprint.toString("hex"));
}
return thisIsMyCertificate;
}
return true;
}
// check if certificate is trusted or untrusted
const crypto_utils = require("node-opcua-crypto");
const pki_folder = process.cwd() + "/pki";
// istanbul ignore next
if (!fs.existsSync(pki_folder)) {
fs.mkdirSync(pki_folder);
}
const pki_untrusted_folder = path.join(pki_folder, "untrusted");
// istanbul ignore next
if (!fs.existsSync(pki_untrusted_folder)) {
fs.mkdirSync(pki_untrusted_folder);
}
const thumbprint = crypto_utils.makeSHA1Thumbprint(serverCertificate);
const certificate_filename = path.join(pki_untrusted_folder, thumbprint.toString("hex") + ".pem");
fs.writeFile(certificate_filename, crypto_utils.toPem(serverCertificate, "CERTIFICATE"), function () {
setImmediate(callback);
});
}
assert(this.privateKey !== invalidPrivateKey, "expecting a valid private key");
const 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(chalk.cyan("DE-----------------------------"));
// debugLog(hexDump(binaryStream.buffer));
debugLog(chalk.cyan("-------------------------------"));
const thumbprint = makeSHA1Thumbprint(asymmetricAlgorithmSecurityHeader.senderCertificate);
debugLog("Certificate thumbprint:", thumbprint.toString("hex"));
}
}
const cert = exploreCertificateInfo(asymmetricAlgorithmSecurityHeader.senderCertificate);
// then verify the signature
const signatureLength = cert.publicKeyLength; // 1024 bits = 128Bytes or 2048=256Bytes or 3072 or 4096
assert(signatureLength === 128 ||
signatureLength === 256 ||
signatureLength === 384 ||
signatureLength === 512);
const chunk = binaryStream.buffer;
const signatureIsOK = asymmetricVerifyChunk(this.cryptoFactory, chunk, asymmetricAlgorithmSecurityHeader.senderCertificate);
// 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(chalk.cyan("EN------------------------------"));
// xx debugLog(hexDump(binaryStream.buffer, 32, 0xFFFFFFFF));
debugLog("---------------------- SENDER CERTIFICATE");
debugLog("thumbprint ", makeSHA1Thumbprint(asymmetricAlgorithmSecurityHeader.senderCertificate).toString("hex"));
}
if (!this.cryptoFactory) {
this._report_error(" Security Policy " + this.securityPolicy + " 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.
const buf = binaryStream.buffer.slice(binaryStream.length);
if (asymmetricAlgorithmSecurityHeader.receiverCertificateThumbprint) {
// this mean that the message has been encrypted ....
assert(this.privateKey !== invalidPrivateKey, "expecting a valid private key");
private _construct_security_header() {
assert(this.hasOwnProperty("securityMode"));
assert(this.hasOwnProperty("securityPolicy"));
this.receiverCertificate = this.serverCertificate ? Buffer.from(this.serverCertificate) : null;
let securityHeader = null;
switch (this.securityMode) {
case MessageSecurityMode.Sign:
case MessageSecurityMode.SignAndEncrypt: {
assert(this.securityPolicy !== SecurityPolicy.None);
// get the thumbprint of the client certificate
const thumbprint = this.receiverCertificate ? makeSHA1Thumbprint(this.receiverCertificate) : null;
securityHeader = new AsymmetricAlgorithmSecurityHeader({
receiverCertificateThumbprint: thumbprint, // thumbprint of the public key used to encrypt the message
securityPolicyUri: toURI(this.securityPolicy),
senderCertificate: this.getCertificateChain() // certificate of the private key used to sign the message
});
break;
}
default:
/* istanbul ignore next */
assert(false, "invalid security mode");
}
this.securityHeader = securityHeader;
}
const SequenceNumberGenerator = require("../src/sequence_number_generator").SequenceNumberGenerator;
const AsymmetricAlgorithmSecurityHeader = require("node-opcua-service-secure-channel").AsymmetricAlgorithmSecurityHeader;
const SymmetricAlgorithmSecurityHeader = require("node-opcua-service-secure-channel").SymmetricAlgorithmSecurityHeader;
const crypto_utils = require("node-opcua-crypto");
const fs = require("fs");
const path = require("path");
const getFixture = require("node-opcua-test-fixtures").getFixture;
const senderCertificate = crypto_utils.readCertificate(getFixture("certs/client_cert_1024.pem"));
const senderPrivateKey = crypto_utils.readKeyPem(getFixture("certs/client_key_1024.pem"));
const receiverCertificate = crypto_utils.readCertificate(getFixture("certs/server_cert_1024.pem"));
const receiverCertificateThumbprint = crypto_utils.makeSHA1Thumbprint(receiverCertificate);
const receiverPublicKey = fs.readFileSync(getFixture("certs/server_public_key_1024.pub"));
const sequenceNumberGenerator = new SequenceNumberGenerator();
/**
* @method iterate_on_signed_message_chunks
* @param buffer
* @param callback {Function}
* @param callback.err {Error}
* @param callback.chunks {Array}
*
*/
function iterate_on_signed_message_chunks(buffer, callback) {
const params = {signatureLength: 128, algorithm: "RSA-SHA1", privateKey: senderPrivateKey};