Create/Convert to CMS/pkcs7 Certificate from Certificate collection and save it as p7b - certificate

I'm trying to convert/Create a PKCS7 "p7b" Certificate from signed certificate pem + chain using BouncyCastle or .net Cryptography class
I tried to use only BC without success, so I use BC only to read pem certs and then transform it to an X509Certificate2 object. What I'm looking for at the end is a pem string at the end starting with "-----BEGIN PKCS7-----" to save it as p7b file
what have I done..
public void DownloadP7bFile(string certId)
{
var records = (DataView)myCertDataSource.Select(DataSourceSelectArguments.Empty);
var selected = Guid.Parse(certId);
foreach (DataRow row in records.Table.Rows)
{
if (!Guid.Parse(row.Field<Guid>("cert_id").ToString()).Equals(selected)) continue;
var filename = row.Field<string>("cert_fqdn_main");
var certContent2 = row.Field<string>("certHash_certificate");
var certissuer = row.Field<string>("certHash_issuer");
DataTable chaincerts = GetChainCertsFromDB(certissuer);
//### get pem string from DB to BC cert objects
Org.BouncyCastle.X509.X509Certificate serverCert = CreateCertObjFromPem(certContent2);
Org.BouncyCastle.X509.X509Certificate interCert = CreateCertObjFromPem(chaincerts.Rows[0].Field<string>("cacert_pemhash"));
Org.BouncyCastle.X509.X509Certificate rootCert = CreateCertObjFromPem(chaincerts.Rows[1].Field<string>("cacert_pemhash"));
//### transform to X509Certificate2 object
System.Security.Cryptography.X509Certificates.X509Certificate2 serverCert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2();
System.Security.Cryptography.X509Certificates.X509Certificate2 interCert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2();
System.Security.Cryptography.X509Certificates.X509Certificate2 rootCert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2();
serverCert2.Import(serverCert.GetEncoded());
interCert2.Import(interCert.GetEncoded());
rootCert2.Import(rootCert.GetEncoded());
//### collect all needed certificates
var collection = new System.Security.Cryptography.X509Certificates.X509Certificate2Collection();
collection.Add(rootCert2);
collection.Add(interCert2);
collection.Add(serverCert2);
var pkcs7ContentBytes = collection.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs7);
//### Test if pkcs7 can be read ###
System.Security.Cryptography.Pkcs.SignedCms sigcms = new System.Security.Cryptography.Pkcs.SignedCms();
sigcms.Decode(pkcs7ContentBytes);
if (sigcms.Certificates.Count > 0)
{
Console.WriteLine("Aussteller: {0}", sigcms.Certificates[0].IssuerName.Name);
Console.WriteLine("Gültig bis {0}", sigcms.Certificates[0].NotAfter);
}
var sigvar2 = sigcms.Encode();
var pkcs7Content = Convert.ToBase64String(pkcs7ContentBytes); //das gute
var certEncodedBytes = Convert.FromBase64String(pkcs7Content);
var certContent = Encoding.UTF8.GetString(certEncodedBytes);
var certContent7 = UTF8Encoding.UTF8.GetString(certEncodedBytes);
var CertContent8 = Convert.ToBase64String(sigvar2);
var CertContent8Bytes = Convert.FromBase64String(CertContent8);
var certfromsig = sigcms.Certificates.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs7);
//var pkcs7cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certEncodedBytes);
//var pkcs7cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(sigvar2);
//System.Security.Cryptography.Pkcs.EnvelopedCms pkcs7Envelop = new System.Security.Cryptography.Pkcs.EnvelopedCms();
//File.WriteAllBytes(#"")
//string utfString = Encoding.UTF8.GetString(pkcs7ContentBytes, 0, pkcs7ContentBytes.Length);
var memoryStream = new MemoryStream(certEncodedBytes);
//var cryptostream = new System.Security.Cryptography.CryptoStream(memoryStream);
//memoryStream.Write(pkcs7ContentBytes, 0, pkcs7ContentBytes.Length);
var test31 = memoryStream.ToArray();
var test32 = memoryStream.Read(certEncodedBytes, 0, certEncodedBytes.Length);
memoryStream.Flush();
memoryStream.Close();
//var test30 = DecoderConverter.ConvertX509ToPkcs7(rootCert, interCert, serverCert);
PerformFileDownload(filename, "p7b", pkcs7Content);
break;
}
}

Related

SageMaker API Header signature issue in flutter

here is my code if anyone can help me this I would be grateful
Map<String, String> signRequest(String param) {
var method = "POST";
var uri = endpoint;
var secretKey = secretKey;
var accessKey = accessKey;
var region = awsRegion;
var service = serviceType;
var host = baseUrl;
var date = DateFormat("yyyyMMdd'T'HHmmss'Z'").format(DateTime.now().toUtc());
var date2 = DateFormat("yyyyMMdd").format(DateTime.now().toUtc());
var requestBody = utf8.encode(json.encode(param.toLowerCase()));
var hashedPayloads = sha256.convert(requestBody).toString().toLowerCase();
var canonicalUri = uri;
var canonicalQuerystring = "";
var canonicalHeaders =
"content-type:application/json\nhost:$host\nx-amz-content-sha256:$hashedPayloads\nx-amz-date:$date\n";
var signedHeaders = "content-type;host;x-amz-content-sha256;x-amz-date";
var canonicalRequest =
"$method\n$canonicalUri\n$canonicalQuerystring\n$canonicalHeaders\n$signedHeaders\n$hashedPayloads";
var credentialScope = "$date2/$region/$service/aws4_request";
var stringToSign =
"${ApiConstants.hmacShaTypeString}\n$date\n$credentialScope\n${sha256.convert(utf8.encode(canonicalRequest))}";
var kSecret = "AWS4$secretKey";
var kDate = Hmac(sha256, utf8.encode(kSecret))
.convert(utf8.encode(date2))
.toString();
var kRegion = Hmac(sha256, utf8.encode(kDate))
.convert(utf8.encode(region))
.toString();
var kService = Hmac(sha256, utf8.encode(kRegion))
.convert(utf8.encode(service))
.toString();
var kSigning = Hmac(sha256, utf8.encode(kService))
.convert(utf8.encode("aws4_request"))
.toString();
var signature = Hmac(sha256, utf8.encode(kSigning))
.convert(utf8.encode(stringToSign))
.toString();
var authorizationHeader =
"${ApiConstants.hmacShaTypeString} Credential=$accessKey/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature";
Map<String, String> headers = {
"Content-Type": "application/json",
"X-Amz-Date": date,
"X-Amz-Content-Sha256": hashedPayloads,
"Authorization": authorizationHeader
};
return headers;
}
Status code: 403
Got this message in response:
{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been"}

Unable to retrieve API keys for a Function App using ListWebAppFunctionKeysArgs

How can I retrieve API keys for a function app in Azure using ListWebAppFunctionKeysArgs?
I have the following method:
public static Output<Dictionary<string, string>?> Get(string resourceGroupName, FunctionApp functionApp)
{
var output =
Output.Tuple(functionApp.Name, functionApp.Name)
.Apply(async tuple => {
var current = Pulumi.Azure.Core.GetClientConfig.InvokeAsync().Result;
var subscriptionId = current.SubscriptionId;
var appName = tuple.Item1;
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken.Value);
var url = $"https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{appName}/functions?api-version=2022-03-01";
var result = await httpClient.GetAsync(url);
if (!result.IsSuccessStatusCode) throw new Exception($"Error: Failed to retrive Azure function names from {appName}");
var json = await result.Content.ReadAsStringAsync();
var root = JsonConvert.DeserializeObject<JsonSupport.AzureFunctionItems.Root>(json);
var items = root.value.Select(async v => {
var data = await ListWebAppFunctionKeys.InvokeAsync(new ListWebAppFunctionKeysArgs {
Name = appName,
FunctionName = v.properties.name,
ResourceGroupName = resourceGroupName
});
return data.Properties;
});
var data = items.SelectMany(v => v.Result).ToList();
return new Dictionary<string, string>(data);
});
return output;
}
Here's the code that I'm struggling with:
var json = await result.Content.ReadAsStringAsync();
var root = JsonConvert.DeserializeObject<JsonSupport.AzureFunctionItems.Root>(json);
var items = root.value.Select(async v => {
var data = await ListWebAppFunctionKeys.InvokeAsync(new ListWebAppFunctionKeysArgs {
Name = appName,
FunctionName = v.properties.name,
ResourceGroupName = resourceGroupName
});
return data.Properties; // Property values are null
});
Here's the result:
In conclusion, how do I acquire API keys for a function app?

Xamarin Essentials Unable to exchange Okta authorization code for token

I was using OpenID and we have to switch to Xamarin.Essentials.WebAuthenticator.
I can get an authorization code from Okta using WebAuthenticator.AuthenticateAsync().
But, everything I try to then translate that code into an access token returns 400 Bad Request.
Okta's API error is "E0000021: HTTP media type not supported exception" and it goes on to say, "Bad request. Accept and/or Content-Type headers likely do not match supported values."
I have tried to follow https://developer.okta.com/blog/2020/07/31/xamarin-essentials-webauthenticator as much as possible, but we are not using the hybrid grant type like he is.
We are using only Authorization Code, which means I have to make a secondary call, and I have spent two days trying to figure out how.
private async Task LoginOktaAsync()
{
try
{
var loginUrl = new Uri(BuildAuthenticationUrl()); // that method is down below
var callbackUrl = new Uri("com.oktapreview.dev-999999:/callback"); // it's not really 999999
var authenticationResult = await Xamarin.Essentials.WebAuthenticator.AuthenticateAsync(loginUrl, callbackUrl);
string authCode;
authenticationResult.Properties.TryGetValue("code",out authCode);
// Everything works fine up to this point. I get the authorization code.
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/token"
+"?grant_type=authorization_code"
+$"&code={authCode}&client_id={OktaConfiguration.ClientId}&code_verifier={codeVerifier}";
var request = new HttpRequestMessage(HttpMethod.Post, url);
var client = new HttpClient();
var response = await client.SendAsync(request); // this generates the 400 error.
}
catch(Exception e)
{
Debug.WriteLine($"Error: {e.Message}");
}
}
Here are the methods that produce the login url and a couple of other things:
public string BuildAuthenticationUrl()
{
var state = CreateCryptoGuid();
var nonce = CreateCryptoGuid();
CreateCodeChallenge();
var url = $"https://dev-999999.oktapreview.com/oauth2/default/v1/authorize?response_type=code"
+ "&response_mode=fragment"
+ "&scope=openid%20profile%20email"
+ "&redirect_uri=com.oktapreview.dev-999999:/callback"
+$"&client_id={OktaConfiguration.ClientId}"
+$"&state={state}"
+$"&code_challenge={codeChallenge}"
+ "&code_challenge_method=S256"
+$"&nonce={nonce}";
return url;
}
private string CreateCryptoGuid()
{
using (var generator = RandomNumberGenerator.Create())
{
var bytes = new byte[16];
generator.GetBytes(bytes);
return new Guid(bytes).ToString("N");
}
}
private string CreateCodeChallenge()
{
codeChallenge = GenerateCodeToVerify();
codeVerifier = codeChallenge;
using (var sha256 = SHA256.Create())
{
var codeChallengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeChallenge));
return Convert.ToBase64String(codeChallengeBytes);
}
}
private string GenerateCodeToVerify()
{
var str = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
Random rnd = new Random();
for (var i = 0; i < 100; i++)
{
str += possible.Substring(rnd.Next(0,possible.Length-1),1);
}
return str;
}
'''
After much online research, I discovered the issue was with how I was doing my post to get the token. This is how I made it work:
public static Dictionary<string, string> JsonDecode(string encodedString)
{
var inputs = new Dictionary<string, string>();
var json = JValue.Parse(encodedString) as JObject;
foreach (KeyValuePair<string, JToken> kv in json)
{
if (kv.Value is JValue v)
{
if (v.Type != JTokenType.String)
inputs[kv.Key] = v.ToString();
else
inputs[kv.Key] = (string)v;
}
}
return inputs;
}
private async Task<string> ExchangeAuthCodeForToken(string authCode)
{
string accessToken = string.Empty;
List<KeyValuePair<string, string>> kvdata = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", authCode),
new KeyValuePair<string, string>("redirect_uri", OktaConfiguration.Callback),
new KeyValuePair<string, string>("client_id", OktaConfiguration.ClientId),
new KeyValuePair<string, string>("code_verifier", codeVerifier)
};
var content = new FormUrlEncodedContent(kvdata);
var request = new HttpRequestMessage(HttpMethod.Post, OktaConfiguration.TokenUrl)
{Content = content, Method = HttpMethod.Post};
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendAsync(request);
string text = await response.Content.ReadAsStringAsync();
Dictionary<string, string> data = JsonDecode(text);
data.TryGetValue("access_token", out accessToken);
return accessToken;
}

Any way to create a JWT token with key size 512? and changing default minimum size requirement of AsymmetricSignatureProvider

I am currently getting following error:
IDX10630: The 'Microsoft.IdentityModel.Tokens.RsaSecurityKey, KeyId: '...', InternalId: '5a946596-9fe6-4c91-8c52-9b140849c7a4'.' for signing cannot be smaller than '2048' bits. KeySize: '512'
I use the following method:
public string GetIdTokenString(Dictionary<string, string> inputClaims, string privateKey)
{
string result = null;
try
{
var tokenHandler = new JwtSecurityTokenHandler();
privateKey = privateKey.Replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", String.Empty).Replace("-----END ENCRYPTED PRIVATE KEY-----", String.Empty);
var privateKeyBytes = Convert.FromBase64String(privateKey);
byte[] privateKeyPasswordBytes = Encoding.UTF8.GetBytes(mypassword);
List<Claim> claims = new List<Claim>();
foreach (var o in inputClaims)
{
claims.Add(new Claim(o.Key, o.Value));
}
int length = 0;
RSA rSA = RSA.Create();
rSA.ImportEncryptedPkcs8PrivateKey(privateKeyPasswordBytes, privateKeyBytes, out length);
RsaSecurityKey securitykey = new RsaSecurityKey(rSA)
{
KeyId = "......"
};
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.UtcNow.AddSeconds(60 * 5),
Audience = ...,
Issuer = .....
};
tokenDescriptor.SigningCredentials = new SigningCredentials(securitykey, SecurityAlgorithms.RsaSha256Signature);
var token = tokenHandler.CreateToken(tokenDescriptor);
if (token != null && token is JwtSecurityToken)
{
result = (token as JwtSecurityToken).RawData;
}
}
catch (Exception ex)
{
Logger.Fatal(ex);
}
return result;
}
there is a code mentioned in post
Error Creating JWT Token using RSA Security Key with key size less than 2048
but I'm not able to run it in .net core 3.1
One more thing is about over riding value in
AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap
Any way i can change value of particular Key?
One thing i have tried which didn't work is
var mainclass = typeof(AsymmetricSignatureProvider)
.GetField(nameof(AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap), BindingFlags.Public | BindingFlags.Static );
var field = mainclass.GetValue(null) as Dictionary<string, int>;
if (field != null)
{
field["RS256"] = 512;
}
var mainclass2 = typeof(AsymmetricSignatureProvider).GetField(nameof(AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap), BindingFlags.Public | BindingFlags.Static);
var field2 = mainclass2.GetValue(null) as Dictionary<string, int>;
if (field2 != null)
{
field2["RS256"] = 512;
}
Following is the solution i have used
var mainclass = typeof(AsymmetricSignatureProvider)
.GetField(nameof(AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForSigningMap), BindingFlags.Public | BindingFlags.Static);
var field = mainclass.GetValue(null) as Dictionary<string, int>;
if (field != null)
{
field["RS256"] = 512;
}
var mainclass2 = typeof(AsymmetricSignatureProvider).GetField(nameof(AsymmetricSignatureProvider.DefaultMinimumAsymmetricKeySizeInBitsForVerifyingMap), BindingFlags.Public | BindingFlags.Static);
var field2 = mainclass2.GetValue(null) as Dictionary<string, int>;
if (field2 != null)
{
field2["RS256"] = 512;
}

upload to S3 with BOM

I want to upload file to S3 with BOM. How can I do this?
var transferUtility = new TransferUtility(client);
string content = "hello";
byte[] b = DefaultEncoding.GetBytes(content);
using (var fileStream = new MemoryStream(b))
{
var request = new TransferUtilityUploadRequest
{
BucketName = bucket,
InputStream = fileStream,
Key = NormalizePath(Path.Combine(folder, file.Name)),
};
}
transferUtility.Upload(request);
When I download file from S3 it's UTF-8, but not UTF-8-BOM
var transferUtility = new TransferUtility(client);
string content = "hello";
byte[] b = Encoding.UTF8.GetPreamble().Concat(DefaultEncoding.GetBytes(content)).ToArray();
using (var fileStream = new MemoryStream(b))
{
var request = new TransferUtilityUploadRequest
{
BucketName = bucket,
InputStream = fileStream,
Key = NormalizePath(Path.Combine(folder, file.Name)),
};
}
transferUtility.Upload(request);