Skip to content

Commit a2b008e

Browse files
committed
use X509IdentityTokenHandler from secure-channel-enhancements-2025-11
1 parent 05a069f commit a2b008e

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

Stack/Opc.Ua.Core/Stack/Types/X509IdentityTokenHandler.cs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ public sealed class X509IdentityTokenHandler : IUserIdentityTokenHandler
4343
public X509IdentityTokenHandler(X509IdentityToken token)
4444
{
4545
m_token = token;
46+
47+
if (m_token.CertificateData != null)
48+
{
49+
m_certificate = CertificateFactory.Create(m_token.CertificateData);
50+
}
51+
52+
m_ownsCertificate = true;
4653
}
4754

4855
/// <summary>
@@ -66,12 +73,29 @@ public X509IdentityTokenHandler(X509Certificate2 certificate)
6673
}
6774

6875
Certificate = certificate;
76+
m_ownsCertificate = true;
6977
m_token = new X509IdentityToken
7078
{
7179
CertificateData = certificate.RawData
7280
};
7381
}
7482

83+
/// <summary>
84+
/// Private constructor for <see cref="Clone"/>. The cloned handler
85+
/// shares the certificate reference but does not own it, so it will
86+
/// not dispose the certificate. This is necessary because the
87+
/// certificate's private key may reside in protected storage and
88+
/// cannot be deep-copied.
89+
/// </summary>
90+
private X509IdentityTokenHandler(
91+
X509IdentityToken token,
92+
X509Certificate2 certificate)
93+
{
94+
m_token = token;
95+
m_certificate = certificate;
96+
m_ownsCertificate = false;
97+
}
98+
7599
/// <summary>
76100
/// The certificate associated with the token.
77101
/// </summary>
@@ -134,16 +158,13 @@ public SignatureData Sign(
134158
byte[] dataToSign,
135159
string securityPolicyUri)
136160
{
137-
X509Certificate2 certificate = Certificate ??
138-
CertificateFactory.Create(m_token.CertificateData);
161+
var info = SecurityPolicies.GetInfo(securityPolicyUri);
139162

140-
SignatureData signatureData = SecurityPolicies.CreateSignatureData(
141-
securityPolicyUri,
142-
certificate,
163+
var signatureData = SecurityPolicies.CreateSignatureData(
164+
info,
165+
m_certificate,
143166
dataToSign);
144167

145-
m_token.CertificateData = certificate.RawData;
146-
147168
return signatureData;
148169
}
149170

@@ -155,17 +176,14 @@ public bool Verify(
155176
{
156177
try
157178
{
158-
X509Certificate2 certificate = Certificate ??
159-
CertificateFactory.Create(m_token.CertificateData);
179+
var info = SecurityPolicies.GetInfo(securityPolicyUri);
160180

161181
bool valid = SecurityPolicies.VerifySignatureData(
162182
signatureData,
163-
securityPolicyUri,
164-
certificate,
183+
info,
184+
m_certificate,
165185
dataToVerify);
166186

167-
m_token.CertificateData = certificate.RawData;
168-
169187
return valid;
170188
}
171189
catch (Exception e)
@@ -180,19 +198,19 @@ public bool Verify(
180198
/// <inheritdoc/>
181199
public void Dispose()
182200
{
183-
// TODOL Utils.SilentDispose(m_certificate);
201+
if (m_ownsCertificate)
202+
{
203+
Utils.SilentDispose(m_certificate);
204+
}
184205
m_certificate = null;
185206
}
186207

187208
/// <inheritdoc/>
188209
public object Clone()
189210
{
190-
return new X509IdentityTokenHandler(Utils.Clone(m_token))
191-
{
192-
// Keep the in-memory certificate instance so private key operations
193-
// continue to work when cloned handlers are used for signing.
194-
Certificate = m_certificate
195-
};
211+
return new X509IdentityTokenHandler(
212+
Utils.Clone(m_token),
213+
m_certificate);
196214
}
197215

198216
/// <inheritdoc/>
@@ -206,6 +224,7 @@ public bool Equals(IUserIdentityTokenHandler other)
206224
}
207225

208226
private readonly X509IdentityToken m_token;
227+
private readonly bool m_ownsCertificate;
209228
private X509Certificate2 m_certificate;
210229
}
211230
}

0 commit comments

Comments
 (0)