|
| 1 | +import logging |
| 2 | + |
1 | 3 | from abc import ABCMeta, abstractmethod |
2 | 4 | from opcua.ua import CryptographyNone, SecurityPolicy |
3 | 5 | from opcua.ua import MessageSecurityMode |
@@ -307,9 +309,63 @@ def encrypted_block_size(self): |
307 | 309 | def decrypt(self, data): |
308 | 310 | return uacrypto.cipher_decrypt(self.cipher, data) |
309 | 311 |
|
| 312 | +class SignerSha256(Signer): |
| 313 | + |
| 314 | + def __init__(self, client_pk): |
| 315 | + require_cryptography(self) |
| 316 | + self.client_pk = client_pk |
| 317 | + self.key_size = self.client_pk.key_size // 8 |
| 318 | + |
| 319 | + def signature_size(self): |
| 320 | + return self.key_size |
| 321 | + |
| 322 | + def signature(self, data): |
| 323 | + return uacrypto.sign_sha256(self.client_pk, data) |
| 324 | + |
| 325 | +class VerifierSha256(Verifier): |
| 326 | + |
| 327 | + def __init__(self, server_cert): |
| 328 | + require_cryptography(self) |
| 329 | + self.server_cert = server_cert |
| 330 | + self.key_size = self.server_cert.public_key().key_size // 8 |
| 331 | + |
| 332 | + def signature_size(self): |
| 333 | + return self.key_size |
| 334 | + |
| 335 | + def verify(self, data, signature): |
| 336 | + uacrypto.verify_sha256(self.server_cert, data, signature) |
| 337 | + |
| 338 | +class SignerHMac256(Signer): |
| 339 | + |
| 340 | + def __init__(self, key): |
| 341 | + require_cryptography(self) |
| 342 | + self.key = key |
| 343 | + |
| 344 | + def signature_size(self): |
| 345 | + return uacrypto.sha256_size() |
| 346 | + |
| 347 | + def signature(self, data): |
| 348 | + return uacrypto.hmac_sha256(self.key, data) |
| 349 | + |
| 350 | + |
| 351 | +class VerifierHMac256(Verifier): |
| 352 | + |
| 353 | + def __init__(self, key): |
| 354 | + require_cryptography(self) |
| 355 | + self.key = key |
| 356 | + |
| 357 | + def signature_size(self): |
| 358 | + return uacrypto.sha256_size() |
| 359 | + |
| 360 | + def verify(self, data, signature): |
| 361 | + expected = uacrypto.hmac_sha256(self.key, data) |
| 362 | + if signature != expected: |
| 363 | + raise uacrypto.InvalidSignature |
310 | 364 |
|
311 | 365 | class SecurityPolicyBasic128Rsa15(SecurityPolicy): |
312 | 366 | """ |
| 367 | + DEPRECATED, do not use anymore! |
| 368 | +
|
313 | 369 | Security Basic 128Rsa15 |
314 | 370 | A suite of algorithms that uses RSA15 as Key-Wrap-algorithm |
315 | 371 | and 128-Bit (16 bytes) for encryption algorithms. |
@@ -344,6 +400,9 @@ def encrypt_asymmetric(pubkey, data): |
344 | 400 | return uacrypto.encrypt_rsa15(pubkey, data) |
345 | 401 |
|
346 | 402 | def __init__(self, server_cert, client_cert, client_pk, mode): |
| 403 | + logger = logging.getLogger(__name__) |
| 404 | + logger.warning("DEPRECATED! Do not use SecurityPolicyBasic128Rsa15 anymore!") |
| 405 | + |
347 | 406 | require_cryptography(self) |
348 | 407 | if isinstance(server_cert, bytes): |
349 | 408 | server_cert = uacrypto.x509_from_der(server_cert) |
@@ -376,6 +435,8 @@ def make_symmetric_key(self, nonce1, nonce2): |
376 | 435 |
|
377 | 436 | class SecurityPolicyBasic256(SecurityPolicy): |
378 | 437 | """ |
| 438 | + DEPRECATED, do not use anymore! |
| 439 | +
|
379 | 440 | Security Basic 256 |
380 | 441 | A suite of algorithms that are for 256-Bit (32 bytes) encryption, |
381 | 442 | algorithms include: |
@@ -410,6 +471,9 @@ def encrypt_asymmetric(pubkey, data): |
410 | 471 | return uacrypto.encrypt_rsa_oaep(pubkey, data) |
411 | 472 |
|
412 | 473 | def __init__(self, server_cert, client_cert, client_pk, mode): |
| 474 | + logger = logging.getLogger(__name__) |
| 475 | + logger.warning("DEPRECATED! Do not use SecurityPolicyBasic256 anymore!") |
| 476 | + |
413 | 477 | require_cryptography(self) |
414 | 478 | if isinstance(server_cert, bytes): |
415 | 479 | server_cert = uacrypto.x509_from_der(server_cert) |
@@ -440,14 +504,78 @@ def make_symmetric_key(self, nonce1, nonce2): |
440 | 504 | self.symmetric_cryptography.Verifier = VerifierAesCbc(sigkey) |
441 | 505 | self.symmetric_cryptography.Decryptor = DecryptorAesCbc(key, init_vec) |
442 | 506 |
|
| 507 | +class SecurityPolicyBasic256Sha256(SecurityPolicy): |
| 508 | + """ |
| 509 | + Security Basic 256Sha256 |
| 510 | + A suite of algorithms that uses Sha256 as Key-Wrap-algorithm |
| 511 | + and 256-Bit (32 bytes) for encryption algorithms. |
| 512 | +
|
| 513 | + - SymmetricSignatureAlgorithm_HMAC-SHA2-256 |
| 514 | + https://tools.ietf.org/html/rfc4634 |
| 515 | + - SymmetricEncryptionAlgorithm_AES256-CBC |
| 516 | + http://www.w3.org/2001/04/xmlenc#aes256-cbc |
| 517 | + - AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 |
| 518 | + http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 |
| 519 | + - AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 |
| 520 | + http://www.w3.org/2001/04/xmlenc#rsa-oaep |
| 521 | + - KeyDerivationAlgorithm_P-SHA2-256 |
| 522 | + http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha256 |
| 523 | + - CertificateSignatureAlgorithm_RSA-PKCS15-SHA2-256 |
| 524 | + http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 |
| 525 | + - Basic256Sha256_Limits |
| 526 | + -> DerivedSignatureKeyLength: 256 bits |
| 527 | + -> MinAsymmetricKeyLength: 2048 bits |
| 528 | + -> MaxAsymmetricKeyLength: 4096 bits |
| 529 | + -> SecureChannelNonceLength: 32 bytes |
| 530 | + """ |
| 531 | + |
| 532 | + URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256" |
| 533 | + signature_key_size = 32 |
| 534 | + symmetric_key_size = 32 |
| 535 | + AsymmetricEncryptionURI = "http://www.w3.org/2001/04/xmlenc#rsa-oaep" |
| 536 | + |
| 537 | + @staticmethod |
| 538 | + def encrypt_asymmetric(pubkey, data): |
| 539 | + return uacrypto.encrypt_rsa_oaep(pubkey, data) |
| 540 | + |
| 541 | + def __init__(self, server_cert, client_cert, client_pk, mode): |
| 542 | + require_cryptography(self) |
| 543 | + if isinstance(server_cert, bytes): |
| 544 | + server_cert = uacrypto.x509_from_der(server_cert) |
| 545 | + # even in Sign mode we need to asymmetrically encrypt secrets |
| 546 | + # transmitted in OpenSecureChannel. So SignAndEncrypt here |
| 547 | + self.asymmetric_cryptography = Cryptography( |
| 548 | + MessageSecurityMode.SignAndEncrypt) |
| 549 | + self.asymmetric_cryptography.Signer = SignerSha256(client_pk) |
| 550 | + self.asymmetric_cryptography.Verifier = VerifierSha256(server_cert) |
| 551 | + self.asymmetric_cryptography.Encryptor = EncryptorRsa( |
| 552 | + server_cert, uacrypto.encrypt_rsa_oaep, 42) |
| 553 | + self.asymmetric_cryptography.Decryptor = DecryptorRsa( |
| 554 | + client_pk, uacrypto.decrypt_rsa_oaep, 42) |
| 555 | + self.symmetric_cryptography = Cryptography(mode) |
| 556 | + self.Mode = mode |
| 557 | + self.server_certificate = uacrypto.der_from_x509(server_cert) |
| 558 | + self.client_certificate = uacrypto.der_from_x509(client_cert) |
| 559 | + |
| 560 | + def make_symmetric_key(self, nonce1, nonce2): |
| 561 | + # specs part 6, 6.7.5 |
| 562 | + key_sizes = (self.signature_key_size, self.symmetric_key_size, 16) |
| 563 | + |
| 564 | + (sigkey, key, init_vec) = uacrypto.p_sha256(nonce2, nonce1, key_sizes) |
| 565 | + self.symmetric_cryptography.Signer = SignerHMac256(sigkey) |
| 566 | + self.symmetric_cryptography.Encryptor = EncryptorAesCbc(key, init_vec) |
| 567 | + |
| 568 | + (sigkey, key, init_vec) = uacrypto.p_sha256(nonce1, nonce2, key_sizes) |
| 569 | + self.symmetric_cryptography.Verifier = VerifierHMac256(sigkey) |
| 570 | + self.symmetric_cryptography.Decryptor = DecryptorAesCbc(key, init_vec) |
443 | 571 |
|
444 | 572 | def encrypt_asymmetric(pubkey, data, policy_uri): |
445 | 573 | """ |
446 | 574 | Encrypt data with pubkey using an asymmetric algorithm. |
447 | 575 | The algorithm is selected by policy_uri. |
448 | 576 | Returns a tuple (encrypted_data, algorithm_uri) |
449 | 577 | """ |
450 | | - for cls in [SecurityPolicyBasic256, SecurityPolicyBasic128Rsa15]: |
| 578 | + for cls in [SecurityPolicyBasic256Sha256, SecurityPolicyBasic256, SecurityPolicyBasic128Rsa15]: |
451 | 579 | if policy_uri == cls.URI: |
452 | 580 | return (cls.encrypt_asymmetric(pubkey, data), |
453 | 581 | cls.AsymmetricEncryptionURI) |
|
0 commit comments