Skip to content

Conversation

@marcschier
Copy link
Collaborator

Strings are immutable and the lifetime of secrets can not be controlled. Use byte[] or char[] instead of strings for secrets, which can be erased after use.

Ported as cherry pick with additional changes and fixes.

Proposed changes

Describe the changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.

Related Issues

  • Fixes #

Types of changes

What types of changes does your code introduce?
Put an x in the boxes that apply. You can also fill these out after creating the PR.

  • Bugfix (non-breaking change which fixes an issue)
  • Enhancement (non-breaking change which adds functionality)
  • Test enhancement (non-breaking change to increase test coverage)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected, requires version increase of Nuget packages)
  • Documentation Update (if none of the other choices apply)

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • I have read the CONTRIBUTING doc.
  • I have signed the CLA.
  • I ran tests locally with my changes, all passed.
  • I fixed all failing tests in the CI pipelines.
  • I fixed all introduced issues with CodeQL and LGTM.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added necessary documentation (if appropriate).
  • Any dependent changes have been merged and published in downstream modules.

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

Strings are immutable and the lifetime of secrets can not be controlled.
Use byte[] or char[] instead of strings for secrets, which can be erased
after use.
@marcschier marcschier requested a review from Copilot October 10, 2025 10:24
@codecov
Copy link

codecov bot commented Oct 10, 2025

Codecov Report

❌ Patch coverage is 70.32967% with 135 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.70%. Comparing base (01ffcee) to head (3a833b5).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
Stack/Opc.Ua.Core/Stack/Client/UserIdentity.cs 46.66% 24 Missing and 8 partials ⚠️
...k/Opc.Ua.Core/Stack/Types/UserNameIdentityToken.cs 70.40% 22 Missing and 7 partials ⚠️
...curity/Certificates/CertificatePasswordProvider.cs 4.54% 20 Missing and 1 partial ⚠️
...ack/Opc.Ua.Core/Stack/Types/IssuedIdentityToken.cs 70.68% 12 Missing and 5 partials ⚠️
...sedUserManagement/UserDatabase/LinqUserDatabase.cs 87.30% 2 Missing and 6 partials ⚠️
...aries/Opc.Ua.Gds.Server.Common/CertificateGroup.cs 33.33% 5 Missing and 1 partial ⚠️
Stack/Opc.Ua.Core/Stack/Types/X509IdentityToken.cs 76.92% 5 Missing and 1 partial ⚠️
...sedUserManagement/UserDatabase/JsonUserDatabase.cs 89.36% 2 Missing and 3 partials ⚠️
...ubSub/Transport/MqttClientProtocolConfiguration.cs 60.00% 2 Missing ⚠️
...ries/Opc.Ua.Security.Certificates/PEM/PEMReader.cs 50.00% 2 Missing ⚠️
... and 5 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3250      +/-   ##
==========================================
- Coverage   57.77%   57.70%   -0.07%     
==========================================
  Files         362      365       +3     
  Lines       79251    79356     +105     
  Branches    13840    13848       +8     
==========================================
+ Hits        45786    45796      +10     
- Misses      29242    29317      +75     
- Partials     4223     4243      +20     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This pull request refactors string usage for secrets in the OPC UA stack to improve security by preventing secrets from being exposed in memory as immutable strings. The changes replace string parameters and properties for passwords and other sensitive data with byte arrays or char arrays, which can be cleared after use.

Key Changes:

  • Refactored user identity tokens and password handling to use byte arrays instead of strings
  • Updated certificate password handling throughout the codebase to use char arrays
  • Modified user database implementations to work with UTF-8 byte arrays for passwords
  • Added proper memory clearing for sensitive data after use

Reviewed Changes

Copilot reviewed 69 out of 70 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
UserIdentity.cs Refactored to use byte arrays for passwords and implement IDisposable
UserNameIdentityToken.cs Created separate file with byte array password handling
IssuedIdentityToken.cs Extracted to separate file with secure token data handling
LinqUserDatabase.cs Updated to use byte arrays for password operations
Various certificate classes Changed password parameters from string to char[] or ReadOnlySpan
Test files Updated to use new UTF-8 string literals and byte array APIs

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@marcschier marcschier marked this pull request as ready for review October 10, 2025 11:11
Copy link
Contributor

@mregen mregen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏼

/// <exception cref="CryptographicException"></exception>
public static ECDsa ImportECDsaPrivateKeyFromPEM(byte[] pemDataBlob, string password = null)
public static ECDsa ImportECDsaPrivateKeyFromPEM(
byte[] pemDataBlob,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also use span here for pemDataBlob?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets handle passwords first. The blob is hopefully password protected. But we should look next at clearing any type of secret info, including PEM/DER/PFX. Let's make that a follow up.

@marcschier marcschier merged commit e505800 into master Oct 12, 2025
120 checks passed
@marcschier marcschier deleted the bytepwds branch October 12, 2025 01:00
/// <summary>
/// An interface to open a certificate store.
/// </summary>
public interface IOpenStore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should name it ICertificateStoreOpener?

@romanett romanett changed the title Refactor string usage for secrets (#394) Refactor string usage for secrets Nov 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants