Closed Demonell closed 5 years ago
Hi.
This method does not exist anymore in dotnet core. X509Certificate2.cs
Why do you even need this non-public method? If you are trying to get CspParameters
of the specified certificate private key you can just simply use CspKeyContainerInfo
property.
var certKey = signerCert.PrivateKey as Gost3410CryptoServiceProvider;
var cspParameters = new CspParameters()
{
KeyContainerName = certKey.CspKeyContainerInfo.KeyContainerName,
ProviderType = certKey.CspKeyContainerInfo.ProviderType,
ProviderName = certKey.CspKeyContainerInfo.ProviderName,
Flags = certKey.CspKeyContainerInfo.MachineKeyStore
? (CspProviderFlags.UseExistingKey | CspProviderFlags.UseMachineKeyStore)
: (CspProviderFlags.UseExistingKey),
KeyNumber = (int)certKey.CspKeyContainerInfo.KeyNumber
};
Also if you are planning to use SignedXml class you need to use gost_x509_xml branch if you are building from the sources, or nuget packages. For now SignedXml is windows only, Linux support is on its way.
I have builded gost_x509_xml branch. CspKeyContainerInfo and PrivateKey getting works perfect. Tried to use SignedXml class and got exception. Same test works fine in net framework.
Exception
System.Security.Cryptography.CryptographicException : SignatureDescription could not be created for the signature algorithm supplied.
at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()
Test
[Theory]
[InlineData(StoreName.My, StoreLocation.CurrentUser, "03F7FA48BE7B112598C9ED6CE4CA968B74541A98", true)]
public void XmlSigner(StoreName storeName, StoreLocation storeLocation, string thumbprint, bool onlyValidCert)
{
var store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadOnly);
var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, onlyValidCert)[0];
store.Close();
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(@"<?xml version='1.0' encoding='UTF-8' standalone='no'?>
<S:Envelope xmlns:S='http://schemas.xmlsoap.org/soap/envelope/' xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
<S:Header>
<wsse:Security S:actor='http://smev.gosuslugi.ru/actors/smev'>
<ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'>
<ds:KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI='#SenderCertificate'/>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsse:BinarySecurityToken EncodingType='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary' ValueType='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3' wsu:Id='SenderCertificate'>
</wsse:BinarySecurityToken>
</wsse:Security>
</S:Header>
<S:Body wsu:Id='body'>
<ws:queryINNFL xmlns:ws='http://ws.unisoft/'>
<smev:Message xmlns:smev='http://smev.gosuslugi.ru/rev110801'>
<smev:Sender>
<smev:Code>MINECONOMSK_SYS_1</smev:Code>
<smev:Name>Mincomsvyaz SK</smev:Name>
</smev:Sender>
<smev:Recipient>
<smev:Code>13312</smev:Code>
<smev:Name>FNS</smev:Name>
</smev:Recipient>
<smev:Originator>
<smev:Code>MINECONOMSK_SYS_1</smev:Code>
<smev:Name>Mincomsvyaz SK</smev:Name>
</smev:Originator>
<smev:TypeCode>2</smev:TypeCode>
<smev:Date>2012-03-13T11:10:54.54Z</smev:Date>
</smev:Message>
<smev:MessageData xmlns:smev='http://smev.gosuslugi.ru/rev110801'>
<smev:AppData wsu:Id='fns-AppData'>
<Document xmlns='http://ws.unisoft/FNSINN/queryINNFL' Id='AB324006-978B-44D4-933D-C5E6DFA8A576'>data</Document>
</smev:AppData>
</smev:MessageData>
</ws:queryINNFL>
</S:Body>
</S:Envelope>");
var signedXml = new SignedXml(xmlDocument)
{
SigningKey = certificate.GetGost3410_2012_256PrivateKey()
};
var reference = new Reference
{
Uri = "",
DigestMethod = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34112012-256"
};
reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
reference.AddTransform(new XmlDsigExcC14NTransform());
signedXml.AddReference(reference);
signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl;
signedXml.SignedInfo.SignatureMethod = "urn:ietf:params:xml:ns:cpxmlsec:algorithms:gostr34102012-gostr34112012-256";
signedXml.ComputeSignature();
var xml = signedXml.GetXml();
Assert.NotNull(signedXml.SignedInfo);
Assert.NotNull(signedXml.SignatureValue);
Assert.NotNull(certificate.RawData);
}
Make sure you reference your local xml and pkcs assemblies. This can be done using these lines in csproj file:
<ItemGroup>
<Reference Include="System.Security.Cryptography.Pkcs">
<HintPath>..\corefx\artifacts\bin\runtime\netcoreapp-Windows_NT-Debug-x64\System.Security.Cryptography.Pkcs.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Xml">
<HintPath>..\corefx\artifacts\bin\runtime\netcoreapp-Windows_NT-Debug-x64\System.Security.Cryptography.Xml.dll</HintPath>
</Reference>
</ItemGroup>
This should be done as these assemblies are not included in corefx package, and distributed by ms as stand-alone packages.
Thank you for quick replies, all works fine now!
Am I getting right if I need make it compatible for linux then I have to change it to
<ItemGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">
<Reference Include="System.Security.Cryptography.Pkcs">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\some-linux-folder\System.Security.Cryptography.Pkcs.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Xml">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\some-linux-folder\System.Security.Cryptography.Xml.dll</HintPath>
</Reference>
<Reference Include="System.Security.Permissions">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\some-linux-folder\System.Security.Permissions.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">
<Reference Include="System.Security.Cryptography.Pkcs">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\netcoreapp-Windows_NT-Debug-x64\System.Security.Cryptography.Pkcs.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Xml">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\netcoreapp-Windows_NT-Debug-x64\System.Security.Cryptography.Xml.dll</HintPath>
</Reference>
<Reference Include="System.Security.Permissions">
<HintPath>..\..\..\corefx\corefx\artifacts\bin\runtime\netcoreapp-Windows_NT-Debug-x64\System.Security.Permissions.dll</HintPath>
</Reference>
</ItemGroup>
And in this case what folder should I use instead of netcoreapp-Windows_NT-Debug-x64 for linux?
For linux you have to replace netstandard assemblies:
git clone https://github.com/CryptoProLLC/NetStandard.Library
mkdir -p ~/.nuget/packages/netstandard.library
cp -r ./NetStandard.Library/nugetReady/netstandard.library ~/.nuget/packages/
Linux runtime artifacts folder is
corefx/artifacts/bin/runtime/netcoreapp-Linux-Debug-x64
Also (as I said before) for now SignedXml and some Pkcs features are windows only, Linux support is on its way. Do not expect anything to work properly in SignedXml on linux.
Got it, thank you!
I'm unable to sign xml smev message since X509Certificate2 has no GetPrivateKeyInfo method.
This test pass in Framework version using CryptoPro .net sdk and does not pass in current corefx fork version.