I have to dare with a web application developed in .NET 1.1 Framework, with no possibilities to upgrade to major versions.
Having said that, I need to encrypt a text using HMAC SHA256.
I see that System.Security.Cryptography namespace in .NET 1.1 provides me a way to has a message in SHA256. But I need to use HMAC (Hash-based Message Authentication Code) with SHA256, so I send not only the text to encrypt, but also a key.
I see that .NET Framework 2.0 and later has an specific class HMACSHA256 to manage this. But haven't found an implementation for .NET 1.1.
¿Any help?
Thanks in advance
You can add to your project the file from Microsoft:
namespace System.Security.Cryptography {
[System.Runtime.InteropServices.ComVisible(true)]
public class HMACSHA256 : HMAC {
//
// public constructors
//
public HMACSHA256 () : this (Utils.GenerateRandom(64)) {}
public HMACSHA256 (byte[] key) {
m_hashName = "SHA256";
#if FEATURE_CRYPTO
m_hash1 = GetHashAlgorithmWithFipsFallback(() => new SHA256Managed(), () => HashAlgorithm.Create("System.Security.Cryptography.SHA256CryptoServiceProvider"));
m_hash2 = GetHashAlgorithmWithFipsFallback(() => new SHA256Managed(), () => HashAlgorithm.Create("System.Security.Cryptography.SHA256CryptoServiceProvider"));
#else
m_hash1 = new SHA256Managed();
m_hash2 = new SHA256Managed();
#endif // FEATURE_CRYPTO
HashSizeValue = 256;
base.InitializeKey(key);
}
}
}
It seems that all calls are based on class that exists in .Net 1.1
Related
Programmed in Visual Studio 2019 on Windows 10.
RFC 2898 encoding process from a .NET Framowork 4.7.2 project. to Xamarin.Form (.NET Standard 2.0) .
The original processing is as follows
var salt = "abcdefg";
var passWord = "password";
var iterations = 5;
var saltbyte = System.Text.Encoding.UTF8. GetBytes(salt);
var Rfc2898 = new System.Security.Cryptography. Rfc2898DeriveBytes(passWord, saltbyte, iterations, System.Security.Cryptography. HashAlgorithmName.SHA256);
Porting it will result in an error in Xamarin, because you can't specify a hash algorithm. You can't specify a hash algorithm.
var Rfc2898 = new System.Security.Cryptography. Rfc2898DeriveBytes(passWord, saltbyte, iterations);
How do I specify a hash algorithm in Xamarin?
Translated with www.DeepL.com/Translator (free version)
It seems like .NET Standard 2.0 doesn't provide the constructor with the HashAlgorithmName argument. It is however present in .NET Standard 2.1. You can easily change your library to use .NET Standard 2.1.
Otherwise, you will have to do that platform specifically instead. Xamarin.iOS and Xamarin.Android do have the constructor available.
So I would create a service to hash your passwords:
public interface IPasswordHasher
{
byte[] GetHashedPassword(string password, string salt, int keySize);
}
Then implement this on both Android and iOS and register it as a Xamarin.Forms DependencyService instance:
using System.Security.Cryptography;
using System.Text.Encoding;
using Xamarin.Forms;
[assembly: Dependency(typeof(MyAwesomeProject.iOS.Services.PasswordHasher))]
namespace MyAwesomeProject.iOS.Services
{
public class PasswordHasher : IPasswordHasher
{
public byte[] GetHashedPassword(string password, string salt, int keySize)
{
var saltbyte = UTF8.GetBytes(salt);
var rfc2898 = new Rfc2898DeriveBytes(password, saltbyte, 1000, HashAlgorithmName.SHA256);
return rfc2898.GetBytes(keySize);
}
}
}
Then when you need to use it as:
var bytes = DependencyService.Get<IDeviceOrientationService>().GetHashedPassword("password", "abcdefg", 20);
I highly recommend that you use more than 5 iterations for your PBKDF2 key derivation. The default is 1000, the higher the better. Of course on mobile, you may hit a performance limitation, but 5 is way too low.
There are examples on the web on how to use bouncy castle library in Java to encrypt with RSA/ECB/OAEPWithSHA256AndMGF1Padding (Example is shown at breaking down RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING). However the bouncy castle library in C# seem to have deviated from Java library in that it is more explicit (hence requires more steps) and I am not able to figure out how to make it work for the above algorithm.
Would appreciate if some body can put a code sample together to encrypt a sample text using RSA/ECB/OAEPWithSHA256AndMGF1Padding.
Unfortunately, even the Java construct is ambiguous as it's open to different and incompatible interpretations, as is shown here. The Java Bouncycastle provider will do one thing with "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" and the Oracle provider will do a different thing.
You can and should specify exactly which behavior you want in both the Java and C# code.
C#:
using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.OpenSsl;
namespace ScratchPad
{
class MainClass
{
public static void OaepEncryptExample()
{
var plain = Encoding.UTF8.GetBytes("The sun also rises.");
// Read in public key from file
var pemReader = new PemReader(File.OpenText(#"/Users/horton/tmp/key-examples/myserver_pub.pem"));
var rsaPub = (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)pemReader.ReadObject();
// create encrypter
var encrypter = new OaepEncoding(new RsaEngine(), new Sha256Digest(), new Sha256Digest(), null);
encrypter.Init(true, rsaPub);
var cipher = encrypter.ProcessBlock(plain, 0, plain.Length);
Console.WriteLine(Convert.ToBase64String(cipher));
}
}
}
Java:
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.openssl.PEMParser;
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
public class OaepExample {
public static void oeapDecrypt() throws Exception {
final PEMParser pemParser = new PEMParser(new FileReader("/Users/horton/tmp/key-examples/myserver.p8"));
final PrivateKeyInfo privKey = (PrivateKeyInfo) pemParser.readObject();
KeyFactory kf = KeyFactory.getInstance("RSA");
RSAPrivateKey rsaPriv = (RSAPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(privKey.getEncoded()));
String cipher64 = "k8AYnTV6RgzQXmD7qn8QwucDXGjbYct+qMVvDmMELTnUcCOeTp82oJ0BryZyEEGXVSZ2BFg95e72Jt9ZAKWNcot2rZ0+POcda8pzY/MfdwIpnSJKITovk8xHL3B/jZDJyQrLMmNPjVV/uBFY2vgKhhLhJzzAJATcGpNdw+gF+XI=";
Cipher decrypter = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
OAEPParameterSpec parameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256,
PSource.PSpecified.DEFAULT);
decrypter.init(Cipher.DECRYPT_MODE, rsaPriv, parameterSpec);
final byte[] plain = decrypter.doFinal(Base64.getDecoder().decode(cipher64));
System.out.println(new String(plain, StandardCharsets.UTF_8));
}
}
I can't get the signature verification working, like it's described here. I'm using BouncyCastle.NetCore 1.8.1.3 and the project is a .NETCoreApp 1.0.
I'm developing on macOS 10.12.1, running dotnet core 1.0.4 and my server is running Ubuntu 16.04.2-x64 running the release version, build as netcore1.0 and ubuntu16.04-x64 app.
The rest of the system runs without problems, except the signature verification.
My validation always returns false.
Here is my service for validating the signature and body:
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace MySkill.Main.Services
{
public class CertificationValidationService : ICertificationValidationService
{
private const string Algorithm = "SHA1withRSA";
public async Task<bool> IsValidSiganture(Stream body, Stream certData, string signature)
{
var pemReader = new Org.BouncyCastle.OpenSsl.PemReader(new StreamReader(certData));
var cert = (Org.BouncyCastle.X509.X509Certificate)pemReader.ReadObject();
using (var sr = new StreamReader(body))
{
var content = await sr.ReadToEndAsync();
var result = CheckRequestSignature(Encoding.UTF8.GetBytes(content), signature, cert);
return result;
}
}
private static bool CheckRequestSignature(byte[] bodyData, string signature, Org.BouncyCastle.X509.X509Certificate cert)
{
byte[] sig = Convert.FromBase64String(signature);
var pubKey = (Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters)cert.GetPublicKey();
var signer = Org.BouncyCastle.Security.SignerUtilities.GetSigner(Algorithm);
signer.Init(false, pubKey);
signer.BlockUpdate(bodyData, 0, bodyData.Length);
return signer.VerifySignature(sig);
}
}
}
Does anybody have a tip, what i'm doing wrong or has used a different framework or apis?
From the code you shared it looks correct. Without seeing the rest of the code I am not sure if the Signature you got is correct. You can take a look at our C# code that passed certification at https://github.com/sophtron/Alexa-Skill-Sophtron and compare against your own to see if there are any differences.
I tried RSACryptoServiceProvider from .net library for signature validation and it had never worked. So I had to switch to BouncyCastle.1.8.1 too and it worked for me.
I am new to working with Accumulo. I need to read/write data from a remote Accumulo through C#.
The only code sample/documentation for C#, I have found is -
Accumulo createBatchScanner range not working as expected
I attempted to compile the code in Xamarin Studio, on a Mac.
The issue I am encountering is with this line:
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Error CS0246: The type or namespace name AccumuloProxy' could not be found. Are you missingorg.apache.accumulo.proxy.thrift' using directive? (CS0246) (AccumuloIntegratorPrototype)
Where can I find the DLLs to add to my CSharp project related to AccumuloProxy client?
Is there a way I can generate the same?
Here is a code fragment:
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
/** connect **/
TTransport transport = new TSocket("xxx.xx.x.xx", 42424);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
Thanks to all for the pointers.
Was able to complete my project.
These are my notes.
A. Versions:
Accumulo 1.5
Thrift 0.90
Mono 3.2.5
B. Strategy/option used to connect to Accumulo from C#:
Accumulo Proxy API
C. Accumulo Proxy with C# bindings:
Performed the following actions on a node running Accumulo
1. Installed Mono 3.2.5
2. Installed Thrift 0.90
3. Configured Accumulo proxy service
Modified the file $ACCUMULO_HOME/proxy/proxy.properties;
Specifically updated the instance name, and zookeeper
4. Started the proxy daemon-
${ACCUMULO_HOME}/bin/accumulo proxy -p ${ACCUMULO_HOME}/proxy/proxy.properties
5.Generated the c# bindings, using the proxy.thrift IDL file
thrift --gen csharp $ACCUMULO_HOME/proxy/thrift/proxy.thrift
This resulted in the creation of a directory called gen-csharp under ${ACCUMULO_HOME}/proxy/thrift/
6. The files under gen-csharp are needed in the C# project, in section D, below.
7. Thrift.dll, is also needed.
D. C# project - Accumulo Client:
1. Created a project of type library.
2. Added the files under gen-csharp in step C5, above to the library
3. Added reference to thrift.dll
4. Built the library
E. Connecting to Accumulo from C#
In the C# project that reads/writes to Accumulo,
1. Added reference - thrift.dll
2. Added reference to the library built in section D, above
3. On the Accumulo server, started the proxy (refer step C4, above)
Here is some sample code, to read data, to try this functionality out..
using System;
using System.Text;
using System.Collections.Generic;
using Thrift.Protocol;
using Thrift.Transport;
namespace AccumuloIntegratorPrototype
{
class MainClass
{
static byte[] GetBytes(string str)
{
return Encoding.ASCII.GetBytes(str);
}
static string GetString(byte[] bytes)
{
return Encoding.ASCII.GetString(bytes);
}
public static void Main (string[] args)
{
try
{
String accumuloProxyServerIP = "xxx.xxx.x.xx";//IP
int accumuloProxyServerPort = 42424;//Port Number
TTransport transport = new TSocket(accumuloProxyServerIP, accumuloProxyServerPort);
transport = new TFramedTransport(transport);
TCompactProtocol protocol = new TCompactProtocol(transport);
transport.Open();
String principal = "root";//Application ID
Dictionary<string, string> passwd = new Dictionary<string,string>();
passwd.Add("password", "xxxxx");//Password
AccumuloProxy.Client client = new AccumuloProxy.Client(protocol);
byte[] loginToken = client.login(principal, passwd);//Login token
//{{
//Read a range of rows from Accumulo
var bScanner = new BatchScanOptions();
Range range = new Range();
range.Start = new Key();
range.Start.Row = GetBytes("d001");
//Need the \0 only if you need to get a single row back
//Otherwise, its not needed
range.Stop = new Key();
range.Stop.Row = GetBytes("d001\0");
bScanner.Ranges = new List<Range>();
bScanner.Ranges.Add(range);
String scanId = client.createBatchScanner(loginToken, "departments", bScanner);
var more = true;
while (more)
{
var scan = client.nextK(scanId, 10);
more = scan.More;
foreach (var entry in scan.Results)
{
Console.WriteLine("Row = " + GetString(entry.Key.Row));
Console.WriteLine("{0} {1}:{2} [{3}] {4} {5}", GetString(entry.Key.Row), GetString(entry.Key.ColFamily), GetString(entry.Key.ColQualifier), GetString(entry.Key.ColVisibility), GetString(entry.Value),(long)entry.Key.Timestamp);
}
}
client.closeScanner(scanId);
client.Dispose();
transport.Close();
}catch (Exception e)
{
Console.WriteLine(e);
}
//}}
}
}
}
Adding Thrift to C# project involves two steps:
Add the C# code that has been generated by means of the Thrift compiler
Build Thrift.DLL and add it as a reference to your project. Alternatively, it is possible to link the code into your project, however not recommended.
The C# code for step 1 is generated from a Thrift IDL file, which is typically part of the project. In your case, the IDL files are located under proxy/src/main/thrift in the Accumulo tree.
The Thrift compiler and library can be downloaded from http://thrift.apache.org. Note that some projects are using a older version of Apache Thrift, which is not necessarily the latest stable. As elserj mentioned in the comments, Accumulo 1.4.x depends on Thrift 0.6.1, Accumulo 1.5.x and greater depend on Thrift 0.9.0.
We're trying to generate an X509 certificate (including the private key) programmatically using C# and the BouncyCastle library. We've tried using some of the code from this sample by Felix Kollmann but the private key part of the certificate returns null. Code and unit test are as below:
using System;
using System.Collections;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
namespace MyApp
{
public class CertificateGenerator
{
/// <summary>
///
/// </summary>
/// <remarks>Based on <see cref="http://www.fkollmann.de/v2/post/Creating-certificates-using-BouncyCastle.aspx"/></remarks>
/// <param name="subjectName"></param>
/// <returns></returns>
public static byte[] GenerateCertificate(string subjectName)
{
var kpgen = new RsaKeyPairGenerator();
kpgen.Init(new KeyGenerationParameters(new SecureRandom(new CryptoApiRandomGenerator()), 1024));
var kp = kpgen.GenerateKeyPair();
var gen = new X509V3CertificateGenerator();
var certName = new X509Name("CN=" + subjectName);
var serialNo = BigInteger.ProbablePrime(120, new Random());
gen.SetSerialNumber(serialNo);
gen.SetSubjectDN(certName);
gen.SetIssuerDN(certName);
gen.SetNotAfter(DateTime.Now.AddYears(100));
gen.SetNotBefore(DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)));
gen.SetSignatureAlgorithm("MD5WithRSA");
gen.SetPublicKey(kp.Public);
gen.AddExtension(
X509Extensions.AuthorityKeyIdentifier.Id,
false,
new AuthorityKeyIdentifier(
SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(kp.Public),
new GeneralNames(new GeneralName(certName)),
serialNo));
gen.AddExtension(
X509Extensions.ExtendedKeyUsage.Id,
false,
new ExtendedKeyUsage(new ArrayList() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") }));
var newCert = gen.Generate(kp.Private);
return DotNetUtilities.ToX509Certificate(newCert).Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12, "password");
}
}
}
Unit test:
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyApp
{
[TestClass]
public class CertificateGeneratorTests
{
[TestMethod]
public void GenerateCertificate_Test_ValidCertificate()
{
// Arrange
string subjectName = "test";
// Act
byte[] actual = CertificateGenerator.GenerateCertificate(subjectName);
// Assert
var cert = new X509Certificate2(actual, "password");
Assert.AreEqual("CN=" + subjectName, cert.Subject);
Assert.IsInstanceOfType(cert.PrivateKey, typeof(RSACryptoServiceProvider));
}
}
}
Just to clarify, an X.509 certificate does not contain the private key. The word certificate is sometimes misused to represent the combination of the certificate and the private key, but they are two distinct entities. The whole point of using certificates is to send them more or less openly, without sending the private key, which must be kept secret. An X509Certificate2 object may have a private key associated with it (via its PrivateKey property), but that's only a convenience as part of the design of this class.
In your first BouncyCastle code example, newCert is really just the certificate and DotNetUtilities.ToX509Certificate(newCert) is built from the certificate only.
Considering that the PKCS#12 format requires the presence of a private key, I'm quite surprised that the following part even works (considering you're calling it on a certificate which can't possibly know the private key):
.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Pkcs12,
"password");
(gen.Generate(kp.Private) signs the certificate using the private key, but doesn't put the private key in the certificate, which wouldn't make sense.)
If you want your method to return both the certificate and the private key you could either:
Return an X509Certificate2 object in which you've initialized the PrivateKey property
Build a PKCS#12 store and returns its byte[] content (as if it was a file). Step 3 in the link you've sent (mirror) explains how to build a PKCS#12 store.
Returning the byte[] (DER) structure for the X.509 certificate itself will not contain the private key.
If your main concern (according to your test case) is to check that the certificate was built from an RSA key-pair, you can check the type of its public key instead.
I realise this is an old post but I found these excellent articles which go through the process:
Using Bouncy Castle from .NET