diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs index 17249e2c8..2d2666947 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/PEMReader.cs @@ -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 { @@ -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 { @@ -190,34 +191,6 @@ private static ECDsa CreateECDsaFromECPrivateKey(ECPrivateKeyParameters eCPrivat } #endif - /// - /// Pads a byte array with leading zeros to reach the specifieed size - /// If the input is allready the given size, it just returns it - /// - /// Provided array to pad - /// The desired total length of byte array after padding - /// - 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 diff --git a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs index f125728a2..ca17f0833 100644 --- a/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs +++ b/Libraries/Opc.Ua.Security.Certificates/Org.BouncyCastle/X509Utils.cs @@ -370,6 +370,35 @@ internal static RSA SetRSAPublicKey(byte[] publicKey) rsaPublicKey.ImportParameters(parameters); return rsaPublicKey; } + + /// + /// Pads a byte array with leading zeros to reach the specifieed size + /// If the input is allready the given size, it just returns it + /// + /// Provided array to pad + /// The desired total length of byte array after padding + /// + 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 } } diff --git a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs index de8480f04..fe4e49861 100644 --- a/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs +++ b/Libraries/Opc.Ua.Security.Certificates/X509Certificate/CertificateBuilder.cs @@ -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 @@ -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); @@ -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) {