How do you decode/decrypt a SignedCMS/PKCS#7 in C# PCL - c#

So, I have an WebAPI that is returning a PKCS#7 file to a client. The client is written as a C# PCL so it can be used in Xamarin iOS and Android projects.
My initial tests worked fine because I was encoding and decoding in my unit tests and could use the Pkcs library. It seems I can't find any way of decoding the data on the client because I don't know of any Pkcs library that works with a PCL.
Can someone tell me how/if this can be done?

So, I did end up switching my project to .netstandard 1.4 and using Portable.BouncyCastle to decode the Cms created on the server side.
Here is the code that I used to decode the Cms. I'm sort of trusting that this is also checking the signature since there is no explicit method for doing that in BouncyCastle like there is via the framework code i.e. CheckSignature().
var cmsParser = new Org.BouncyCastle.Cms.CmsSignedDataParser(dataBytes);
var cmsSignedContent = cmsParser.GetSignedContent();
var contentStream = cmsSignedContent.ContentStream;
var memoryStream = new MemoryStream();
contentStream.CopyTo(memoryStream);
byte[] contentBytes = memoryStream.ToArray();
var decodedContent = Encoding.UTF8.GetString(contentBytes);
In addition I added this to verify the signer info:
cmsParser.GetSignedContent().Drain();
var certStore = cmsParser.GetCertificates("Collection");
var signerInfos = cmsParser.GetSignerInfos();
var signers = signerInfos.GetSigners();
foreach (SignerInformation signer in signers)
{
var certCollection = certStore.GetMatches(signer.SignerID);
foreach (Org.BouncyCastle.X509.X509Certificate cert in certCollection)
{
var result = signer.Verify(cert);
if (!result)
{
throw new Exception("Certificate verification error, the signer could not be verified.");
}
}
}
I'm not 100% sure if this is all I need to do but my client's will communicate via SSL and they are using an HMAC auth with an appId and client secret so I'm not so concerned with in transit issues. I'm basically transferring a "license" file and I want to make sure the contents are not tampered with after it has been saved on the client device.
If anyone has any suggestions or concerns with this please let me know.
Thanks.

I currently use PCLCrypto to encrypt and decrypt using PKCS#7 on the client (in a Xamarin Forms project). I assume it will do what you need as well.
The PKCS#7 wiki example can be found here

Related

Web service call with a SHA-384 ECDSA certificate

For the project I am working on I have to convert the following legacy code to use a SHA-384 ECDSA certificate, .NET Framework 4.8 as target.
Is it possible natively in C# or do I need some help like BouncyCastle lib and how?
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
[...]
// Certificate is in PKCS#12 format and contains a private key, certificate is password protected with the session id
var certificateBytes = Convert.FromBase64String(base64Certificate.ToString());
var certificate = new X509Certificate2();
certificate.Import(certificateBytes, sessionId, X509KeyStorageFlags.DefaultKeySet);
var result = (HttpWebRequest)WebRequest.Create( url );
result.Headers.Add( "x-jwt-authorization", $"Bearer {JSONWebToken}" );
result.ClientCertificates.Add( Certificate );
var response = (HttpWebResponse)request.GetResponse();
I tried to find a solution/explanation online but didn't work (keep getting a "Not supported" for the PrivateKey property when trying to import the certificate, and a 403 Forbidden as server response).
Also if I want to keep backward compatibility, how do I distinguish if the Base64 string contains a X509 or a SHA one to support both?

JWT Invalid Signatures in .NET libraries

I am currently struggling with creating signatures with any .net library to access Twitch api endpoints. The jwt.io page always says the signature is invalid when I copy paste my generated jwt there. When I edit the secret the signature is obviously adjusted and when I use the adjusted jwt I can make the Twitch api call without a problem. When I use my generated jwt I always end up with a 401 authentication failed.
I tried pretty much all of the .net libraries now and all of them generate a wrong signature for HS256… I am not sure what I do wrong since I am new to JWT and couldn’t find anything that points me to the right direction. Here is my code to generate the jwt using the jwt.net library (https://github.com/jwt-dotnet/jwt). Would highly appreciate if someone could help me with this.
var payload = new Dictionary<string, object>
{
{ "exp", DateTimeOffset.Now.AddSeconds(360).ToUnixTimeSeconds()},
{ "user_id", "668312333"},
{ "role", "external"},
};
var secret = Encoding.UTF8.GetString(Convert.FromBase64String("MY SHARED EXTENSION SECRET FROM TWITCH"));
IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(payload, secret);
you need to set the secret to be a byte array as that is what is needed by the underlying library :-
var secret = Convert.FromBase64String("MY SHARED EXTENSION SECRET FROM TWITCH");

Decrypting forms authentication token (AES, SHA1) in node js

Has anyone had luck decrypting a .NET forms authentication generated cookie in node js using the crypto library?
I'm using AES for encryption and SHA1 for validation in .NET forms authentication mechanism.
I was wondering if someone had this problem before and solved it?
I played with this and made the following code for Node.js:
var crypto = require('crypto');
var iconv = require('iconv-lite');
function hash(password) {
// your validation key from web.config + 00 at the end
var buf = new Buffer('...00', 'hex');
var hmac = crypto.createHmac('sha1', buf);
// convert password from utf8 to UTF16
var pass = iconv.encode(password, 'utf16le');
hmac.update(pass);
return hmac.digest('base64');
}
console.log(hash('test'));
Use it to compare hashes from your database.
It depends on web.config settings.
You can see the source code of Encryp and Decrypt here with all the different possibilities (Framework20SP1, Framework20SP2, etc)
https://github.com/Microsoft/referencesource/blob/master/System.Web/Security/FormsAuthentication.cs
For example, on Framework20SP1 the cookie looks like: Enc(IV+SerializedTicket+Modifier)+HMAC(Enc(IV+SerializedTicket+Modifier))

C# Generate a non self signed client CX509Certificate Request without a CA using the certenroll.dll

I have a self signed root certificate that I generated in C# using CERTENROLL.dll's CX509CertificateRequest Certificate functionality.
I would like to write a function that generates client certificates signed by my root using the same API. However the only CertEnroll option I can find that does not generate a self signed certificate requires a authenticated CA.
There seems to be a flag for setting a SignerCertificate but it always fails to initialize.
//Initialize cert
var cert = new CX509CertificateRequestCertificate();
//take care of signer
cert.Issuer = issuen;
CSignerCertificate sc = new CSignerCertificate();
var raw = SEScert.GetRawCertData();
var rawStr=Convert.ToBase64String(raw);
sc.Initialize(false, X509PrivateKeyVerify.VerifyNone,
EncodingType.XCN_CRYPT_STRING_BASE64, rawStr); //fails here
cert.SignerCertificate = sc;
Does anyone know how I can generate a client CX509CertificateRequest signed by my root?
Any help or advice would be greatly appreciated.
I was able to solve this.
The encoding of SEScert is a hex string not base64 also the machine context should be set to true not false the correct code looks as follows:
ISignerCertificate signerCertificate = new CSignerCertificate();
signerCertificate.Initialize(true, X509PrivateKeyVerify.VerifyNone,EncodingType.XCN_CRYPT_STRING_HEX, SEScert.GetRawCertDataString());
cert.SignerCertificate = (CSignerCertificate)signerCertificate;
Hope this helps others in the future.

Decode Signed Request Without Authentication

Are we able to use the Facebook C# SDK to decode the signed_request parameter that is passed to the Facebook Tab page, without using Authentication? Basically, I am looking for a way to decode and parse the page JSON object that the signed_request contains.
I am looking for the .NET C# equivelent to accomplishing the same type of decode in this PHP example: Seamless way to check if user likes page
I am just pasting same answer I have answered in another post.
Fans-only content in facebook with asp.net C# sdk
You get signed request when your web page is loaded within facebook canvas app; you should be able to parse signed request something similar to following:
if (Request.Params["signed_request"] != null)
{
string payload = Request.Params["signed_request"].Split('.')[1];
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var o = JObject.Parse(json);
var lPid = Convert.ToString(o.SelectToken("page.id")).Replace("\"", "");
var lLiked = Convert.ToString(o.SelectToken("page.liked")).Replace("\"", "");
var lUserId= Convert.ToString(o.SelectToken("user_id")).Replace("\"", "");
}
You need to add reference to json libraries in order to parse signed requestin C#, download from http://json.codeplex.com/
Also refere to How to decode OAuth 2.0 for Canvas signed_request in C#? if you are worndering about signed request.
What do you mean 'without authentication'? The signed request is signed with your app secret, so you can decode it regardless of whether the current user has authorised your app
{edit} I now realise you're referring to a library named Authentication{/edit}
If you find another library or reimplement the algorithm for HMAC SHA-256 and a base64url decoder i'm sure you could do it without using that specific library, but it's probably easier to just use it

Categories

Resources