'Convert Bouncy Castle RSA sign to .NET 5 sign
I'm trying to remove the dependency on Bouncy Castle for a PowerShell module, whilst keeping it cross platform. Currently I have the following code:
function Invoke-CastleSign ($EncodedText, $PrivateKey) {
Add-Type -Path $PSScriptRoot\lib\BouncyCastle.Crypto.dll
$pemStream = [IO.StringReader]::new($PrivateKey)
$pemReader = [Org.BouncyCastle.OpenSsl.PemReader]::new($pemStream)
$Key = [Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair]($pemReader.ReadObject())
$engine = [Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding]::new([Org.BouncyCastle.Crypto.Engines.RsaEngine]::new())
$engine.Init($true, $Key.Private)
$signature = $engine.ProcessBlock($encodedText, 0, $encodedText.Length)
[System.Convert]::ToBase64String($signature)
}
When I sign the letter 'a', I get the following result:
$encodedText = [Text.Encoding]::UTF8.GetBytes('a')
$PrivateKey = '-----BEGIN RSA PRIVATE KEY-----MIICWwIBAAKBgQClhYmqKK7MX2puBabxDFJsiXCprewDOXIdQ5eY3yZJ9z2Bco7OcXPlyGk2K54Qw/hWo+pRLU+5Wj8P6ZSRkIZQ6me36yCd6kzcHORsIQHBTCCOie4L+uqJGewTDe3G5L/tPE8gzH+uRcoLs+VMr2iMEC2M/M+OFVYvIvq6H9pQ8wIDAQABAoGAM7ZLszCwo8Mvoh378RUzbxtlam2e7cb1wvTKGQWmlbc7rQSYXyEM335EeJsZ8Az5uj/NxfzNCpCKYTNNqkin3YBaEUk9UcWAYTEJD481Xz4T23zkAocevy+zMk68Egcr/Ibv0oAuGXahI1bI9dpxu8wwXMICfw4d1pR4yaYOfCkCQQDmmu4l6IqD8cg/gl4OiJwb1YEOP+Pss6PCbPoJI0Iqbq/0D7kuT4uLTlr28HZUEs/uWuZHZWfIxI5O0UcsYAvnAkEAt7/QhKiAypDbaIa+djxmWVOynTUPJdd+ZghhkyVn976h4fsYWTnnrg9jq5X+YvEh3tRaL3D2hGvcPUhxTXkRFQJAY0w7V992JbKrA43jamawsduRos0oG/iOf13lnKGuEA9xfKp4ltRxxh6LVOHeUf13w68okX283tqkXJQJDbad6QJAfieYfuu9eNXZfbs9Gqo/TsbzE5HxM3bvFhhc/YyqA+MC+8bMIb5qvQtdz9lsTPvm2DkNLhMtfR8cl4qcF6euPQJAOAm1i19n8OWwN5rCB5cxztSOAPbvTBH0acyGSbYhN5pn4YBG+5nzkPs0cSuC2HCnhS+hB+l5vHN4anGXGI+pbQ==-----END RSA PRIVATE KEY-----'
Invoke-CastleSign -EncodedText $encodedText -PrivateKey $PrivateKey
Result
NumMBAtUR2a6uievEbgKNPsC9nqEoaVRG7DweA64deW0Zaa8w3l4VKcxUUCv9NmMj+9H0cVFhIKOEgKkHNZ4fvfVxgCizVHgNLuN5Zf1hfRgN8NR1nUZVcknVGEl6xTwAZP+CAbn0lHt4MGJBH2QlVT0okm2C0XTMO+HRXdRes8=
Here is what I currently have for .NET, as you can see the output is different to the above result:
function Invoke-NETSign ($EncodedText, $PrivateKey) {
$rsa = [System.Security.Cryptography.RSA]::create()
$rsa.ImportFromPem($PrivateKey.ToCharArray())
$signature = $rsa.SignData($encodedText, [Security.Cryptography.HashAlgorithmName]::SHA1, [Security.Cryptography.RSASignaturePadding]::Pkcs1)
[System.Convert]::ToBase64String($signature)
}
Invoke-NETSign -EncodedText $encodedText -PrivateKey $PrivateKey
Result
A4PMhZhjdQWx92810Kmd2udpXcY7pUJJ5xeI5go2x/sKvpwXyJfkR1kSuQrRSlWXeA2ZAZAzKNLtrUMfNvspIOSBEWb0Yu19ROjzS7ciZnqPwdb5VQdRu1RprQzGW7EpUmOh4w9kUgOy34KkWW2TCLX4WC3WoNw9MPyrBX+HP+I=
I've been able to reproduce the result above with Bouncy Castle, but what I actually need is the same output from Invoke-CastleSign. I can post the code for the Bouncy Castle version if required. The requirements from the API are RSA and SHA1 / SHA256, the above code is all SHA1. Chef Server API
Edit: There was a comment stating that this can't be performed in .NET 5+, it mentioned that the code is not using a digest, or at least a null digest. However in the code used by Chef, they are validating that the digest is either OpenSSL::Digest::SHA1 or OpenSSL::Digest::SHA256, see their code mixlib-authentication
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|