Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify SetECDsaPublicKey and padd with leading zeros (#2962) #2963

Merged
merged 1 commit into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
using Opc.Ua.Security.Certificates.BouncyCastle;

namespace Opc.Ua.Security.Certificates
{
Expand Down Expand Up @@ -168,9 +169,9 @@ private static ECDsa CreateECDsaFromECPrivateKey(ECPrivateKeyParameters eCPrivat
var d = eCPrivateKeyParameters.D.ToByteArrayUnsigned();

// pad all to the same length since ToByteArrayUnsigned might drop leading zeroes
x = PadWithLeadingZeros(x, keySizeBytes);
y = PadWithLeadingZeros(y, keySizeBytes);
d = PadWithLeadingZeros(d, keySizeBytes);
x = X509Utils.PadWithLeadingZeros(x, keySizeBytes);
y = X509Utils.PadWithLeadingZeros(y, keySizeBytes);
d = X509Utils.PadWithLeadingZeros(d, keySizeBytes);


var ecParams = new ECParameters {
Expand All @@ -190,34 +191,6 @@ private static ECDsa CreateECDsaFromECPrivateKey(ECPrivateKeyParameters eCPrivat
}
#endif

/// <summary>
/// Pads a byte array with leading zeros to reach the specifieed size
/// If the input is allready the given size, it just returns it
/// </summary>
/// <param name="arrayToPad">Provided array to pad</param>
/// <param name="desiredSize">The desired total length of byte array after padding</param>
/// <returns></returns>
private static byte[] PadWithLeadingZeros(byte[] arrayToPad, int desiredSize)
{
if (arrayToPad.Length == desiredSize)
{
return arrayToPad;
}

int paddingLength = desiredSize - arrayToPad.Length;
if (paddingLength < 0)
{
throw new ArgumentException($"Input byte array is larger than the desired size {desiredSize} bytes.");
}

var paddedArray = new byte[desiredSize];

// Right-align the arrayToPad into paddedArray
Buffer.BlockCopy(arrayToPad, 0, paddedArray, paddingLength, arrayToPad.Length);

return paddedArray;

}
#endregion

#region Internal class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,35 @@ internal static RSA SetRSAPublicKey(byte[] publicKey)
rsaPublicKey.ImportParameters(parameters);
return rsaPublicKey;
}

/// <summary>
/// Pads a byte array with leading zeros to reach the specifieed size
/// If the input is allready the given size, it just returns it
/// </summary>
/// <param name="arrayToPad">Provided array to pad</param>
/// <param name="desiredSize">The desired total length of byte array after padding</param>
/// <returns></returns>
internal static byte[] PadWithLeadingZeros(byte[] arrayToPad, int desiredSize)
{
if (arrayToPad.Length == desiredSize)
{
return arrayToPad;
}

int paddingLength = desiredSize - arrayToPad.Length;
if (paddingLength < 0)
{
throw new ArgumentException($"Input byte array is larger than the desired size {desiredSize} bytes.");
}

var paddedArray = new byte[desiredSize];

// Right-align the arrayToPad into paddedArray
Buffer.BlockCopy(arrayToPad, 0, paddedArray, paddingLength, arrayToPad.Length);

return paddedArray;

}
#endregion
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Math.EC;
using Opc.Ua.Security.Certificates.BouncyCastle;
#endif

namespace Opc.Ua.Security.Certificates
Expand Down Expand Up @@ -297,35 +298,36 @@ public override ICertificateBuilderCreateForECDsaAny SetECDsaPublicKey(byte[] pu
var publicKeyInfo = SubjectPublicKeyInfo.GetInstance(asn1Obj);
var algParams = publicKeyInfo.Algorithm.Parameters;
var x962Params = X962Parameters.GetInstance(algParams);
var ecPoint = publicKeyInfo.PublicKey.GetBytes();

ECParameters ecParameters = new ECParameters();
X9ECParameters ecParametersAsn1 = null;

var domainParameters = asymmetricPubKeyParameters.Parameters;
var q = asymmetricPubKeyParameters.Q;
// calculate keySize round up (bitLength + 7) / 8
int keySizeBytes = (domainParameters.N.BitLength + 7) / 8;

if (x962Params.IsNamedCurve)
{
// Named
var namedCurveOid = (DerObjectIdentifier)x962Params.Parameters;
string curveName = namedCurveOid.Id;

var ecCurve = System.Security.Cryptography.ECCurve.CreateFromOid(new Oid(curveName));
ecParameters.Curve = ecCurve;
}
else
{
// Explicit but still need to create the curve as named since the platform does not support it's creation
// otherwise
ecParametersAsn1 = X9ECParameters.GetInstance(x962Params.Parameters);
ecParameters.Curve = BouncyCastle.X509Utils.IdentifyEccCurveByCoefficients(ecParametersAsn1.Curve.A.GetEncoded(),
ecParametersAsn1.Curve.B.GetEncoded());// instead of ecParametersAsn1.Curve;

// Explicit parameters
var a = X509Utils.PadWithLeadingZeros(domainParameters.Curve.A.ToBigInteger().ToByteArrayUnsigned(), keySizeBytes);
var b = X509Utils.PadWithLeadingZeros(domainParameters.Curve.B.ToBigInteger().ToByteArrayUnsigned(), keySizeBytes);
ecParameters.Curve = BouncyCastle.X509Utils.IdentifyEccCurveByCoefficients(a,b);
}

//Extract the public key coordinates
var publicKeyPoint = new X9ECPoint(ecParametersAsn1.Curve, ecPoint).Point;
var x = X509Utils.PadWithLeadingZeros(q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(), keySizeBytes);
var y = X509Utils.PadWithLeadingZeros(q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned(), keySizeBytes);
// Use the Q point
ecParameters.Q = new System.Security.Cryptography.ECPoint {
X = publicKeyPoint.AffineXCoord.ToBigInteger().ToByteArrayUnsigned(),
Y = publicKeyPoint.AffineYCoord?.ToBigInteger().ToByteArrayUnsigned()
X = x,
Y = y
};

m_ecdsaPublicKey.ImportParameters(ecParameters);
Expand All @@ -334,6 +336,7 @@ public override ICertificateBuilderCreateForECDsaAny SetECDsaPublicKey(byte[] pu
#else
m_ecdsaPublicKey.ImportSubjectPublicKeyInfo(publicKey, out bytes);
#endif
SetECCurve(m_ecdsaPublicKey.ExportParameters(false).Curve);
}
catch (Exception e)
{
Expand Down
Loading