How to make sure certificate is not changed? - c#

There is an issue came into my mind.
Is there any common way to make an app running only when there is an installed certificate in the system. And I want such a certificate to be issued and verified by my self-signed certificate?
I can get a certificate by it's name from the storage, but how do I make sure such a certificate is signed by my self-signed certificate and nobody have issued a certificate with the same name and replaced the one in the local storage?
Or in other words, how do I make sure the certificate which signed the certificate at local storage is not a forged one?
I'm sorry if its not correct and|or clear question, but I'll be happy to have help regarding it.

Very good question indeed.
There is always a possibility of the end-user creating a valid certificate chain with your subject name and as the issuer, another for the issuer ceritificate, all up to the root.
What they canot do is to sign those certifcates with the issuer certificate's private key.
Therefore, the code below loads the application certificate from the personal certificate store of the current user, then, loads the issuer certificate of the issuer from the resources and verifies the signature on the application certificate installed on the client machine using the public key of the issuer certificate.
In my source code, the issuer certificate is added to the resources with the key IssuerCertificate
I am actually fond of coming out with a solution like this.
In the code I mention an encoding ASN.1. Check it here if you need
static void Main(string[] args)
{
string expectedSubjectName = "My Application";
X509Certificate2 issuerCertificate = new X509Certificate2(Resource1.IssuerCertificate);
string expectedIssuerName = issuerCertificate.Subject;
bool result = VerifyCertificateIssuer(expectedSubjectName, expectedIssuerName, issuerCertificate);
}
private static void ThrowCertificateNotFoundException(string expectedSubjectName, string expectedIssuerName, bool isThumbprintMismatch)
{
if (isThumbprintMismatch)
{
// Notification for possible certificate forgery
}
throw new SecurityException("A certificate with subject name " + expectedSubjectName + " issued by " + expectedIssuerName + " is required to run this application");
}
private static X509Certificate2 GetCertificate(string expectedSubjectName, string expectedIssuerName)
{
X509Store personalCertificateStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
personalCertificateStore.Open(OpenFlags.ReadOnly);
X509CertificateCollection certificatesBySubjectName = personalCertificateStore.Certificates.Find(X509FindType.FindBySubjectName, expectedSubjectName, true);
if (certificatesBySubjectName.Count == 0)
{
ThrowCertificateNotFoundException(expectedSubjectName, expectedIssuerName, false);
}
X509Certificate2 matchingCertificate = null;
foreach (X509Certificate2 certificateBySubjectName in certificatesBySubjectName)
{
if (certificateBySubjectName.Issuer == expectedIssuerName)
{
matchingCertificate = certificateBySubjectName;
break;
}
}
if (matchingCertificate == null)
{
ThrowCertificateNotFoundException(expectedSubjectName, expectedIssuerName, false);
}
return matchingCertificate;
}
private static bool VerifyCertificateIssuer(string expectedSubjectName, string expectedIssuerName, X509Certificate2 issuerCertificate)
{
X509Certificate2 matchingCertificate = GetCertificate(expectedSubjectName, expectedIssuerName);
X509Chain chain = new X509Chain();
chain.Build(matchingCertificate);
// bool x = Encoding.ASCII.GetString(chain.ChainElements[1].Certificate.RawData) == Encoding.ASCII.GetString(issuerCertificate.RawData);
byte[] certificateData = matchingCertificate.RawData;
MemoryStream asn1Stream = new MemoryStream(certificateData);
BinaryReader asn1StreamReader = new BinaryReader(asn1Stream);
// The der encoded certificate structure is like this:
// Root Sequence
// Sequence (Certificate Content)
// Sequence (Signature Algorithm (like SHA256withRSAEncryption)
// Sequence (Signature)
// We need to decode the ASN.1 content to get
// Sequence 0 (which is the actual certificate content that is signed by the issuer, including the sequence definition and tag number and length)
// Sequence 2 (which is the signature. X509Certificate2 class does not give us that information. The year is 2015)
// Read the root sequence (ignore)
byte leadingOctet = asn1StreamReader.ReadByte();
ReadTagNumber(leadingOctet, asn1StreamReader);
ReadDataLength(asn1StreamReader);
// Save the current position because we will need it for including the sequence header with the certificate content
int sequence0StartPosition = (int)asn1Stream.Position;
leadingOctet = asn1StreamReader.ReadByte();
ReadTagNumber(leadingOctet, asn1StreamReader);
int sequence0ContentLength = ReadDataLength(asn1StreamReader);
int sequence0HeaderLength = (int)asn1Stream.Position - sequence0StartPosition;
sequence0ContentLength += sequence0HeaderLength;
byte[] sequence0Content = new byte[sequence0ContentLength];
asn1Stream.Position -= 4;
asn1StreamReader.Read(sequence0Content, 0, sequence0ContentLength);
// Skip sequence 1 (signature algorithm) since we don't need it and assume that we know it because we own the issuer certificate
// This sequence, containing the algorithm used during the signing process IS HIDDEN FROM US BY DEFAULT. The year is 2015.
// What should have been done for real is, to get the algorithm ID (hash algorithm and asymmetric algorithm) and to use those
// algorithms during the verification process
leadingOctet = asn1StreamReader.ReadByte();
ReadTagNumber(leadingOctet, asn1StreamReader);
int sequence1ContentLength = ReadDataLength(asn1StreamReader);
byte[] sequence1Content = new byte[sequence1ContentLength];
asn1StreamReader.Read(sequence1Content, 0, sequence1ContentLength);
// Read sequence 2 (signature)
// The actual signature of the certificate IS HIDDEN FROM US BY DEFAULT. The year is 2015.
leadingOctet = asn1StreamReader.ReadByte();
ReadTagNumber(leadingOctet, asn1StreamReader);
int sequence2ContentLength = ReadDataLength(asn1StreamReader);
byte unusedBits = asn1StreamReader.ReadByte();
sequence2ContentLength -= 1;
byte[] sequence2Content = new byte[sequence2ContentLength];
asn1StreamReader.Read(sequence2Content, 0, sequence2ContentLength);
// At last, we have the data that is signed and the signature.
bool verificationResult = ((RSACryptoServiceProvider)issuerCertificate.PublicKey.Key)
.VerifyData
(
sequence0Content,
CryptoConfig.MapNameToOID("SHA256"),
sequence2Content
);
return verificationResult;
}
private static byte[] ReadTagNumber(byte leadingOctet, BinaryReader inputStreamReader)
{
List<byte> byts = new List<byte>();
byte temporaryByte;
if ((leadingOctet & 0x1F) == 0x1F) // More than 1 byte is used to specify the tag number
{
while (((temporaryByte = inputStreamReader.ReadByte()) & 0x80) > 0)
{
byts.Add((byte)(temporaryByte & 0x7F));
}
byts.Add(temporaryByte);
}
else
{
byts.Add((byte)(leadingOctet & 0x1F));
}
return byts.ToArray();
}
private static int ReadDataLength(BinaryReader inputStreamReader)
{
byte leadingOctet = inputStreamReader.ReadByte();
if ((leadingOctet & 0x80) > 0)
{
int subsequentialOctetsCount = leadingOctet & 0x7F;
int length = 0;
for (int i = 0; i < subsequentialOctetsCount; i++)
{
length <<= 8;
length += inputStreamReader.ReadByte();
}
return length;
}
else
{
return leadingOctet;
}
}
private static byte[] GetTagNumber(byte leadingOctet, BinaryReader inputStreamReader, ref int readBytes)
{
List<byte> byts = new List<byte>();
byte temporaryByte;
if ((leadingOctet & 0x1F) == 0x1F) // More than 1 byte is used to specify the tag number
{
while (((temporaryByte = inputStreamReader.ReadByte()) & 0x80) > 0)
{
readBytes++;
byts.Add((byte)(temporaryByte & 0x7F));
}
byts.Add(temporaryByte);
}
else
{
byts.Add((byte)(leadingOctet & 0x1F));
}
return byts.ToArray();
}

Related

C# generate certificate based on template from Active Directory Certificate Services

Using the CA web page https://{CAServerName}/certsrv/certrqma.asp, I can manually create a request based on the template and install the certificate after approval.
How to do the same but in c#?
This is my first time working with certificates and this is what I got.
While searching, I found 2 useful articles:
How to work with certreq
How to create a certificate request with CertEnroll and .NET (C#)
In the first case, I understood how to form a request.
Here is an example:
req.inf
[NewRequest]
Subject = ""
KeyLength = 2048
RequestType = PKCS10
ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0"
[RequestAttributes]
CertificateTemplate = ""
Subject - Certificate-Details-Subject.
CertificateTemplate - get frendly name from Certificate-Details-Subject, search TemplatePropFriendlyName in "certutil.exe -Template" and get TemplatePropCommonName.
certreq -q -new req.inf req.req
certreq -config "CAHostName.domain.local\CAName" -submit "req.req" "cert.cer"
certreq -accept "cert.cer"
In the second case, I took example and reduced it a bit.
public class TestCertManager
{
private const int CC_DEFAULTCONFIG = 0;
private const int CC_UIPICKCONFIG = 0x1;
private const int CR_IN_BASE64 = 0x1;
private const int CR_IN_FORMATANY = 0;
private const int CR_IN_PKCS10 = 0x100;
private const int CR_DISP_ISSUED = 0x3;
private const int CR_DISP_UNDER_SUBMISSION = 0x5;
private const int CR_OUT_BASE64 = 0x1;
private const int CR_OUT_CHAIN = 0x100;
// Create request
public string CreateRequest()
{
string subject = "<subject>";
string templateName = "<templateName>";
// Create all the objects that will be required
CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10();
CX509PrivateKey objPrivateKey = new CX509PrivateKey();
CCspInformation objCSP = new CCspInformation();
CCspInformations objCSPs = new CCspInformations();
CX500DistinguishedName objDN = new CX500DistinguishedName();
CX509Enrollment objEnroll = new CX509Enrollment();
// Initialize the csp object using the desired Cryptograhic Service Provider (CSP)
objCSP.InitializeFromName("Microsoft Enhanced Cryptographic Provider v1.0");
// Add this CSP object to the CSP collection object
objCSPs.Add(objCSP);
objPrivateKey.Length = 2048;
objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;
objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
objPrivateKey.MachineContext = false;
// Provide the CSP collection object (in this case containing only 1 CSP object)
// to the private key object
objPrivateKey.CspInformations = objCSPs;
// Create the actual key pair
objPrivateKey.Create();
// provide a template name
objPkcs10.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser,objPrivateKey, templateName);
// Encode the name in using the Distinguished Name object
objDN.Encode(
subject,
X500NameFlags.XCN_CERT_NAME_STR_NONE
);
// Assing the subject name by using the Distinguished Name object initialized above
objPkcs10.Subject = objDN;
// Create enrollment request
objEnroll.InitializeFromRequest(objPkcs10);
string strRequest = objEnroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64);
return strRequest;
}
// Submit request to CA and get response
public string SendRequest(string strRequest)
{
// Create all the objects that will be required
CCertConfig objCertConfig = new CCertConfig();
CCertRequest objCertRequest = new CCertRequest();
string strCAConfig = #"CAHostName\CAName";
int iDisposition;
string strDisposition;
string strCert;
// Submit the request
iDisposition = objCertRequest.Submit(CR_IN_BASE64 | CR_IN_FORMATANY, strRequest, null, strCAConfig);
// Check the submission status
if (CR_DISP_ISSUED != iDisposition) // Not enrolled
{
strDisposition = objCertRequest.GetDispositionMessage();
if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
{
Console.WriteLine("The submission is pending: " + strDisposition);
return "";
}
else // Failed
{
Console.WriteLine("The submission failed: " + strDisposition);
Console.WriteLine("Last status: " + objCertRequest.GetLastStatus().ToString());
return "";
}
}
// Get the certificate
strCert = objCertRequest.GetCertificate(CR_OUT_BASE64 | CR_OUT_CHAIN);
return strCert;
}
// Install response from CA
public void AcceptPKCS7(string strCert)
{
// Create all the objects that will be required
CX509Enrollment objEnroll = new CX509Enrollment();
// Install the certificate
objEnroll.Initialize(X509CertificateEnrollmentContext.ContextUser);
objEnroll.InstallResponse(
InstallResponseRestrictionFlags.AllowUntrustedRoot,
strCert,
EncodingType.XCN_CRYPT_STRING_BASE64,
null
);
Console.WriteLine("Certificate installed!");
}
}
I'm still looking for the best solution, but at least I have 2 working options.

How import and export RSAParameters keys to file without making a change to the keys in C#

I'm writing a digital signing program using C# and I use RSACryptoServiceProvider class that generates public and private keys and signatures depending on the file. If in the program, I check the signature with the public key, signature and file, it works correctly but If I save my keys to any format in the file, In other words, I will change their format and return to the first state It doesn't work. because I can not turn it into RSAParameters correctly. please guide me?
Simple example test to show the change:
var publicParams = rsaWrite.ExportParameters(false); // Generate the public key.
var testpublicParams = publicParams;
string st = Encoding.ASCII.GetString(publicParams.Modulus);
testpublicParams.Modulus = Encoding.ASCII.GetBytes(st);
if(publicParams.Modulus != testpublicParams.Modulus) {
Console.WriteLine("The key has been changed.");
}
You can get PublicKey as string format and save it on the other text file.
public static string PublicKey(string certSubject)
{
var my = new X509Store(StoreName.My, StoreLocation.LocalMachine);
my.Open(OpenFlags.ReadOnly);
RSACryptoServiceProvider csp = null;
byte[] publicKeyByte = null;
foreach (var cert in my.Certificates)
{
if (cert.Subject.Contains(certSubject))
{
csp = (RSACryptoServiceProvider)cert.PublicKey.Key;
publicKeyByte = cert.PublicKey.EncodedKeyValue.RawData;
}
}
if (csp == null)
{
throw new Exception("No valid cert was found");
}
var publicKey = new StringBuilder();
publicKey.AppendLine("-----BEGIN PUBLIC KEY-----");
publicKey.AppendLine(Convert.ToBase64String(publicKeyByte, Base64FormattingOptions.InsertLineBreaks));
publicKey.AppendLine("-----END PUBLIC KEY-----");
return publicKey.ToString();
}
This code has two problems:
The use of Encoding.ASCII.GetBytes is wrong because it might have a non-ASCII characters so we use the Convert.ToBase64String.
publicParams.Modulus is C# byte array so != probably not the right answer so we use SequenceEqual.
And the key will not change.
var rsaWrite = new RSACryptoServiceProvider();
var publicParams = rsaWrite.ExportParameters(false); // Generate the public key.
var testpublicParams = publicParams;
string st = Convert.ToBase64String(publicParams.Modulus);
testpublicParams.Modulus = Convert.FromBase64String(st);
if (!publicParams.Modulus.SequenceEqual(testpublicParams.Modulus))
{
Console.WriteLine("The key has been changed.");
}
else
{
Console.WriteLine("The key has not been changed. :D");
}

NetSuite C# Console App Web Services Token Authentication Returning "Ambiguous Authentication"

I'm trying to get my integrations updated to handle this forced use of token authentication for NetSuite web services. However, I'm stuck getting the following:
[System.Web.Services.Protocols.SoapException] Ambiguous authentication
I've tried various things with no improvement. Doesn't seem to matter if I use a token created beforehand, or have one generated. I'm not creating a "Cookie Container", or adding a standard Passport object. I've tried a few different methods for generating a signature and a nonce value. I've even switched between SHA1 and SHA256 thinking that might make a difference. I'm going to include my code here. Hopefully someone can see what I'm doing wrong.
FYI, there are some components in here from trying what I found in this post: Ambiguous Authentication in Netsuite Token Based API call
static void Main(string[] args) {
NameValueCollection _dataCollection = ConfigurationManager.AppSettings;
NSCreds crd = new NSCreds(_dataCollection); /// just building a data object to handle credentials and keys
NSWS ns = new NSWS(crd, _dataCollection["appId"]); // token passport gets built here
// now to make a call to just get a single file from the File Cabinet
RecordRef pullFile = new RecordRef();
pullFile.type = RecordType.file;
pullFile.typeSpecified = true;
pullFile.internalId = _dataCollection["fileId"];
ReadResponse rres = ns.service.get(pullFile); // this line throws the error highlighted above
}
public NSWS(NSCreds c, String appId) {
CheckConnectionSecurity(); // makes sure connection security is set to TLS 1.2
_pageSize = 100;
service = new NetSuiteService();
service.Timeout = 1000 * 60 * 60 * 2;
service.tokenPassport = prepareTokenPassport(c);
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.applicationId = appId;
service.applicationInfo = appInfo;
}
public TokenPassport prepareTokenPassport(NSCreds c) {
long TimeStamp = ComputeTimestamp();
String nonce = CreateNonce_1();
NSToken token = null;
if (String.IsNullOrEmpty(c.tokenId) && String.IsNullOrEmpty(c.tokenSecret)) {
token = GetToken(c.customerKey, c); // make calls to NetSuite to generate token data and build custom object
} else {
token = new NSToken(c.tokenId,c.tokenSecret); // build custom object from apps settings data
}
String signature = ComputeSignature(c.account, c.customerKey, c.customerSecret, token.tokenId, token.tokenSecret, nonce, TimeStamp);
TokenPassport tokenPassport = new TokenPassport();
tokenPassport.account = c.account;
tokenPassport.consumerKey = c.customerKey;
tokenPassport.token = token.tokenId;
tokenPassport.nonce = nonce;
tokenPassport.timestamp = TimeStamp;
TokenPassportSignature signatureElement = new TokenPassportSignature();
signatureElement.algorithm = "HMAC-SHA1"; // "HMAC-SHA256";
signatureElement.Value = signature;
tokenPassport.signature = signatureElement;
return tokenPassport;
}
private static long ComputeTimestamp() {
return ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
private String CreateNonce_1() {
int length = 20;
String AllowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder nonce = new StringBuilder();
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] rnd = new byte[1];
for (int i = 0; i < length; i++) {
while (true) {
rng.GetBytes(rnd);
char c = (char)rnd[0];
if (AllowedChars.IndexOf(c) != (-1)) {
nonce.Append(rnd[0]);
break;
}
}
}
return nonce.ToString();
}
private static string CreateNonce_2() {
return Guid.NewGuid().ToString("N");
}
private String CreateNonce_3() {
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] data = new byte[20];
rng.GetBytes(data);
int value = Math.Abs(BitConverter.ToInt32(data, 0));
return value.ToString();
}
private string ComputeSignature(String account, String cKey, String cSecret, String token, String tokenSecret, String nonce, long timeStamp) {
String baseString = String.Format("{0}&{1}&{2}&{3}&{4}",account,cKey,token,nonce,timeStamp);
String key = String.Format("{0}&{1}", cSecret, tokenSecret);
// previous method for encoding the signature
// Mac is a custom object found from another post here
// EncryptionMethods is an enumeration from that same post
/*
//using (var secretKey = new SecretKeySpec(GetBytes(key), EncryptionMethods.HMACSHA256))
using (var secretKey = new SecretKeySpec(GetBytes(key), EncryptionMethods.HMACSHA1))
using (Mac mac = new Mac(secretKey, baseString)) {
return mac.AsBase64();
}
*/
//HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(key));
HMACSHA1 hashObject = new HMACSHA1(Encoding.UTF8.GetBytes(key));
byte[] signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(baseString));
string encodedSignature = Convert.ToBase64String(signature);
return encodedSignature;
}
It turns out that the problem was setting the Application ID while also specifying a Token Passport. Doing so actually creates a conflict with the system not knowing which to use for authentication, since the token itself references the Application ID internally. So, removed the bit where the Application ID was being set to the service object and everything started working correctly.
Try to use this code for token based authentication
TokenPassport tokenPassport = new TokenPassport();
tokenPassport.account = account; //Account ID
tokenPassport.consumerKey = consumerKey; //Consumer Key
tokenPassport.token = tokenId; // Token ID
tokenPassport.nonce = nonce; //It is some calculated value with the help of RNGCryptoServiceProvider class.
tokenPassport.timestamp = timestamp;
tokenPassport.signature = signature; // It is TokenPassportSignature
TokenPassportSignature also uses Account ID, Token ID & Token Secret. It has some algorithms.

RSA Cryptography and saving to database (c#)

I don't have deep information about cryptography ,but as I gathered some information,as an asymmetric solution I want to use RSA and here is the code which I found,I want to store an encrypted password into database and decrypt it whenever I want to get the user information,I mean these two actions don't happen respectively and whenever I like I can select from database and decrypt the previously save data.I know that there is something wrong with the generated keys,but because of low knowledge on this subject I cannot handle it.
I get the following Exception on decryption.
The parameter is incorrect.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
Encryption Class:
public static class AsymmetricEncryption
{
private static bool _optimalAsymmetricEncryptionPadding = false;
public static void GenerateKeys(int keySize, out string publicKey, out string publicAndPrivateKey)
{
using (var provider = new RSACryptoServiceProvider(keySize))
{
publicKey = provider.ToXmlString(false);
publicAndPrivateKey = provider.ToXmlString(true);
}
}
public static string EncryptText(string text, int keySize, string publicKeyXml)
{
var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKeyXml);
return Convert.ToBase64String(encrypted);
}
public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
int maxLength = GetMaxDataLength(keySize);
if (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicKeyXml);
return provider.Encrypt(data, _optimalAsymmetricEncryptionPadding);
}
}
public static string DecryptText(string text, int keySize, string publicAndPrivateKeyXml)
{
var decrypted = Decrypt(Convert.FromBase64String(text), keySize, publicAndPrivateKeyXml);
return Encoding.UTF8.GetString(decrypted);
}
public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicAndPrivateKeyXml);
return provider.Decrypt(data, _optimalAsymmetricEncryptionPadding);
}
}
public static int GetMaxDataLength(int keySize)
{
if (_optimalAsymmetricEncryptionPadding)
{
return ((keySize - 384) / 8) + 7;
}
return ((keySize - 384) / 8) + 37;
}
public static bool IsKeySizeValid(int keySize)
{
return keySize >= 384 &&
keySize <= 16384 &&
keySize % 8 == 0;
}
}
Encrypt usage:
const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.EncryptText(text, keySize, publicKey);
Decrypt usage:
const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.DecryptText(text, keySize, publicKey);
I read the encrypted text from a table.And I like to decrypt it.
Please help me solve this issue.
Thanks in advance
Snippet link
Let me stop you right here, before you actually figure out the exception.
IT IS A HORRIBLE IDEA TO STORE PASSWORDS REVERSIBLY, regardless what encryption you use. There are memory scrubbers and a million other problems with that scheme.
Passwords are to be HASHED, NOT ENCRYPTED. The difference is that hashes are hard to reverse if implemented properly. Use BCrypt or SHA2 or SHA3 or some other good hashing algorithms, use proper salt.
Here's an example, but consult someone knowledgeable before using in production, I may have bugs, the methods are coded for simplicity and may be too simple:
public string GetHash(string secret, string salt = null)
{
var hasher = SHA256Managed.Create();
salt = salt ?? Guid.NewGuid().ToString("N"); // 128 bit salt
var hashResult = hasher.ComputeHash(Encoding.UTF8.GetBytes(salt+"|"+what));
return "SHA256|" + salt + "|" + Convert.ToBase64String(hashResult);
}
Now you can store the string you get from this function in your DB and the next time a password comes in (over HTTPS, I hope) you can check it by getting the salt from the string stored in DB:
public bool CheckSecretHash(string secret, string hashFromDB){
var hashParts = hashFromDB.Split('|'); // string[3]
var rehash = GetHash(secret, hashParts[1]);
return hashFromDB == rehash;
}
Bonus points: challenge-response. ALWAYS USE HTTPS.

C# RunAs /Smartcard

My application used to accept username/password to authenticate to a remote share (on Windows server) and then get the file listings etc.
public int ConnectNetResource(string server, string user, string password, ref string driveLeter) {
NETRESOURCE net = new NETRESOURCE();
net.dwScope = 0;
net.dwType = 0;
net.dwDisplayType = 0;
net.dwUsage = 0;
net.lpRemoteName = server;
net.lpLocalName = driveLeter;
net.lpProvider = null;
return WNetAddConnection2(ref net, password, user, 0);
}
Now, we need to authenticate using SmartCard. I have code to GetSmartCards, but I do not know how to make use of the certificate to authenticate.
public static X509Certificate2 GetClientCertificate()
{
X509Certificate2 certificate = null;
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
// Nothing to do if no cert found.
if (store.Certificates != null && store.Certificates.Count > 0)
{
if (store.Certificates.Count == 1)
{
// Return the certificate present.
certificate = store.Certificates[0];
}
else
{
// Request the user to select a certificate
var certificates = X509Certificate2UI.SelectFromCollection(store.Certificates, "Digital Certificates", "Select a certificate from the following list:", X509SelectionFlag.SingleSelection);
// Check if one has been returned
if (certificates != null && certificates.Count > 0)
certificate = certificates[0];
}
}
}
finally
{
store.Close();
}
return certificate;
}
GetClientCertificate function will return a user selected certificate, now HOW do I use this certificate to connect to a remote share. What API's or .dll can i use.
Btw, I am a windows engineer who can google code and make it work somehow. Will greatly appreciate a working code. Thank you.

Categories