def activate_session(self, username=None, password=None, certificate=None): """ Activate session using either username and password or private_key """ params = ua.ActivateSessionParameters() challenge = b"" if self.security_policy.server_certificate is not None: challenge += self.security_policy.server_certificate if self._server_nonce is not None: challenge += self._server_nonce params.ClientSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature( challenge) params.LocaleIds.append("en") if not username and not certificate: params.UserIdentityToken = ua.AnonymousIdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.Anonymous, b"anonymous") elif certificate: params.UserIdentityToken = ua.X509IdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.Certificate, b"certificate_basic256") params.UserIdentityToken.CertificateData = uacrypto.der_from_x509( certificate) # specs part 4, 5.6.3.1: the data to sign is created by appending # the last serverNonce to the serverCertificate sig = uacrypto.sign_sha1(self.user_private_key, challenge) params.UserTokenSignature = ua.SignatureData() params.UserTokenSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.UserTokenSignature.Signature = sig else: params.UserIdentityToken = ua.UserNameIdentityToken() params.UserIdentityToken.UserName = username policy_uri = self.server_policy_uri(ua.UserTokenType.UserName) if not policy_uri or policy_uri == security_policies.POLICY_NONE_URI: # see specs part 4, 7.36.3: if the token is NOT encrypted, # then the password only contains UTF-8 encoded password # and EncryptionAlgorithm is null if self.server_url.password: self.logger.warning("Sending plain-text password") params.UserIdentityToken.Password = password params.UserIdentityToken.EncryptionAlgorithm = '' elif self.server_url.password: pubkey = uacrypto.x509_from_der( self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce passwd = bytes(password, "utf8") if self._server_nonce is not None: passwd += self._server_nonce etoken = ua.pack_bytes(passwd) data, uri = security_policies.encrypt_asymmetric( pubkey, etoken, policy_uri) params.UserIdentityToken.Password = data params.UserIdentityToken.EncryptionAlgorithm = uri params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.UserName, b"username_basic256") return self.uaclient.activate_session(params)
def cert_to_string(der): if not der: return '[no certificate]' try: from opcua.crypto import uacrypto except ImportError: return "{0} bytes".format(len(der)) cert = uacrypto.x509_from_der(der) return uacrypto.x509_to_string(cert)
def _encrypt_password(self, password, policy_uri): pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce passwd = bytes(password, "utf8") if self._server_nonce is not None: passwd += self._server_nonce etoken = ua.pack_bytes(passwd) data, uri = security_policies.encrypt_asymmetric(pubkey, etoken, policy_uri)
def _encrypt_password(self, password, policy_uri): pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce passwd = password.encode("utf8") if self._server_nonce is not None: passwd += self._server_nonce etoken = ua.ua_binary.Primitives.Bytes.pack(passwd) data, uri = security_policies.encrypt_asymmetric(pubkey, etoken, policy_uri) return data, uri
def activate_session(self, username=None, password=None, certificate=None): """ Activate session using either username and password or private_key """ params = ua.ActivateSessionParameters() challenge = b"" if self.security_policy.server_certificate is not None: challenge += self.security_policy.server_certificate if self._server_nonce is not None: challenge += self._server_nonce params.ClientSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature(challenge) params.LocaleIds.append("en") if not username and not certificate: params.UserIdentityToken = ua.AnonymousIdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.Anonymous, b"anonymous") elif certificate: params.UserIdentityToken = ua.X509IdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.Certificate, b"certificate_basic256") params.UserIdentityToken.CertificateData = uacrypto.der_from_x509(certificate) # specs part 4, 5.6.3.1: the data to sign is created by appending # the last serverNonce to the serverCertificate sig = uacrypto.sign_sha1(self.user_private_key, challenge) params.UserTokenSignature = ua.SignatureData() params.UserTokenSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.UserTokenSignature.Signature = sig else: params.UserIdentityToken = ua.UserNameIdentityToken() params.UserIdentityToken.UserName = username policy_uri = self.server_policy_uri(ua.UserTokenType.UserName) if not policy_uri or policy_uri == security_policies.POLICY_NONE_URI: # see specs part 4, 7.36.3: if the token is NOT encrypted, # then the password only contains UTF-8 encoded password # and EncryptionAlgorithm is null if self.server_url.password: self.logger.warning("Sending plain-text password") params.UserIdentityToken.Password = password params.UserIdentityToken.EncryptionAlgorithm = '' elif self.server_url.password: pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce passwd = bytes(password, "utf8") if self._server_nonce is not None: passwd += self._server_nonce etoken = ua.pack_bytes(passwd) data, uri = security_policies.encrypt_asymmetric(pubkey, etoken, policy_uri) params.UserIdentityToken.Password = data params.UserIdentityToken.EncryptionAlgorithm = uri params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.UserName, b"username_basic256") return self.uaclient.activate_session(params)
def set_security(self, policy, certificate_path, private_key_path, server_certificate_path=None, mode=ua.MessageSecurityMode.SignAndEncrypt): """ Set SecureConnection mode. Call this before connect() """ if server_certificate_path is None: # load certificate from server's list of endpoints endpoints = self.connect_and_get_server_endpoints() endpoint = Client.find_endpoint(endpoints, mode, policy.URI) server_cert = uacrypto.x509_from_der(endpoint.ServerCertificate) else: server_cert = uacrypto.load_certificate(server_certificate_path) cert = uacrypto.load_certificate(certificate_path) pk = uacrypto.load_private_key(private_key_path) self.security_policy = policy(server_cert, cert, pk, mode) self.bclient.set_security(self.security_policy)
def set_security(self, policy, certificate_path, private_key_path, server_certificate_path=None, mode=ua.MessageSecurityMode.SignAndEncrypt): """ Set SecureConnection mode. Call this before connect() """ if server_certificate_path is None: # load certificate from server's list of endpoints endpoints = self.connect_and_get_server_endpoints() endpoint = Client.find_endpoint(endpoints, mode, policy.URI) server_cert = uacrypto.x509_from_der(endpoint.ServerCertificate) else: server_cert = uacrypto.load_certificate(server_certificate_path) cert = uacrypto.load_certificate(certificate_path) pk = uacrypto.load_private_key(private_key_path) self.security_policy = policy(server_cert, cert, pk, mode) self.uaclient.set_security(self.security_policy)
def __init__(self, server_cert, client_cert, client_pk, mode): require_cryptography(self) if isinstance(server_cert, bytes): server_cert = uacrypto.x509_from_der(server_cert) # even in Sign mode we need to asymmetrically encrypt secrets # transmitted in OpenSecureChannel. So SignAndEncrypt here self.asymmetric_cryptography = Cryptography( MessageSecurityMode.SignAndEncrypt) self.asymmetric_cryptography.Signer = SignerRsa(client_pk) self.asymmetric_cryptography.Verifier = VerifierRsa(server_cert) self.asymmetric_cryptography.Encryptor = EncryptorRsa( server_cert, uacrypto.encrypt_rsa_oaep, 42) self.asymmetric_cryptography.Decryptor = DecryptorRsa( client_pk, uacrypto.decrypt_rsa_oaep, 42) self.symmetric_cryptography = Cryptography(mode) self.Mode = mode self.server_certificate = uacrypto.der_from_x509(server_cert) self.client_certificate = uacrypto.der_from_x509(client_cert)
def activate_session(self, username=None, password=None, certificate=None): """ Activate session using either username and password or private_key """ params = ua.ActivateSessionParameters() challenge = self.security_policy.server_certificate + self._server_nonce params.ClientSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature( challenge) params.LocaleIds.append("en") if not username and not certificate: params.UserIdentityToken = ua.AnonymousIdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.Anonymous, b"anonymous") elif certificate: params.UserIdentityToken = ua.X509IdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.Certificate, b"certificate_basic256") params.UserIdentityToken.CertificateData = uacrypto.der_from_x509( certificate) # specs part 4, 5.6.3.1: the data to sign is created by appending # the last serverNonce to the serverCertificate sig = uacrypto.sign_sha1(self.user_private_key, challenge) params.UserTokenSignature = ua.SignatureData() params.UserTokenSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.UserTokenSignature.Signature = sig else: params.UserIdentityToken = ua.UserNameIdentityToken() params.UserIdentityToken.UserName = username if self.server_url.password: pubkey = uacrypto.x509_from_der( self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce etoken = ua.pack_bytes( bytes(password, "utf8") + self._server_nonce) #data = uacrypto.encrypt_basic256(pubkey, etoken) data = uacrypto.encrypt_rsa_oaep(pubkey, etoken) params.UserIdentityToken.Password = data params.UserIdentityToken.PolicyId = self.server_policy_id( ua.UserTokenType.UserName, b"username_basic256") params.UserIdentityToken.EncryptionAlgorithm = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep' return self.bclient.activate_session(params)
def __init__(self, server_cert, client_cert, client_pk, mode): logger = logging.getLogger(__name__) logger.warning("DEPRECATED! Do not use SecurityPolicyBasic256 anymore!") require_cryptography(self) if isinstance(server_cert, bytes): server_cert = uacrypto.x509_from_der(server_cert) # even in Sign mode we need to asymmetrically encrypt secrets # transmitted in OpenSecureChannel. So SignAndEncrypt here self.asymmetric_cryptography = Cryptography( MessageSecurityMode.SignAndEncrypt) self.asymmetric_cryptography.Signer = SignerRsa(client_pk) self.asymmetric_cryptography.Verifier = VerifierRsa(server_cert) self.asymmetric_cryptography.Encryptor = EncryptorRsa( server_cert, uacrypto.encrypt_rsa_oaep, 42) self.asymmetric_cryptography.Decryptor = DecryptorRsa( client_pk, uacrypto.decrypt_rsa_oaep, 42) self.symmetric_cryptography = Cryptography(mode) self.Mode = mode self.server_certificate = uacrypto.der_from_x509(server_cert) self.client_certificate = uacrypto.der_from_x509(client_cert)
def get_server_certificate(self): """ Request the server for its certificate or just return if already known :returns: server certificate """ if self._cert: return self._cert self.get_client().connect() matching_endpoints = [ ep for ep in self.get_client().get_endpoints() if ep.SecurityPolicyUri == self._config.security_policy.URI ] self.get_client().disconnect() if matching_endpoints: self._cert = uacrypto.x509_from_der( matching_endpoints[0].ServerCertificate) return self._cert logger.error('Could not find matching endpoint for URI %s', self._config.server['security_policy'].URI) return None
def activate_session(self, username=None, password=None, certificate=None): """ Activate session using either username and password or private_key """ params = ua.ActivateSessionParameters() challenge = self.security_policy.server_certificate + self._server_nonce params.ClientSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.ClientSignature.Signature = self.security_policy.asymmetric_cryptography.signature(challenge) params.LocaleIds.append("en") if not username and not certificate: params.UserIdentityToken = ua.AnonymousIdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.Anonymous, b"anonymous") elif certificate: params.UserIdentityToken = ua.X509IdentityToken() params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.Certificate, b"certificate_basic256") params.UserIdentityToken.CertificateData = uacrypto.der_from_x509(certificate) # specs part 4, 5.6.3.1: the data to sign is created by appending # the last serverNonce to the serverCertificate sig = uacrypto.sign_sha1(self.user_private_key, challenge) params.UserTokenSignature = ua.SignatureData() params.UserTokenSignature.Algorithm = b"http://www.w3.org/2000/09/xmldsig#rsa-sha1" params.UserTokenSignature.Signature = sig else: params.UserIdentityToken = ua.UserNameIdentityToken() params.UserIdentityToken.UserName = username if self.server_url.password: pubkey = uacrypto.x509_from_der(self.security_policy.server_certificate).public_key() # see specs part 4, 7.36.3: if the token is encrypted, password # shall be converted to UTF-8 and serialized with server nonce etoken = ua.pack_bytes(bytes(password, "utf8") + self._server_nonce) #data = uacrypto.encrypt_basic256(pubkey, etoken) data = uacrypto.encrypt_rsa_oaep(pubkey, etoken) params.UserIdentityToken.Password = data params.UserIdentityToken.PolicyId = self.server_policy_id(ua.UserTokenType.UserName, b"username_basic256") params.UserIdentityToken.EncryptionAlgorithm = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep' return self.bclient.activate_session(params)