so I am building a message encryption application in C# and Obj-c using Visual Studio Mac and Xcode, I have a text field where the user types their password to decrypt the message. However, after trying several things, I an unable to print the NSTextField as a string to compare it to the password string which is imprinted into the text file.
I have already tried NSString * = [DateCreated stringValue];This did not work.
Code put into Visual Studio by Xcode after designing GUI in ViewController.Designer.cs:
[Outlet]
public static AppKit.NSTextField DateCreated { get; set; }
Code for message decryption where attempting to compare password strings for decryption of message, encryption is working perfectly.
public static string Decrypted(string encrypted)
{
DateTime creation = File.GetCreationTime(#"/Users/bopc/encryptedmessagehere.txt");
string asString = creation.ToString("MM/dd/yyyy hh:mm:ss tt");
var created = ViewController.verify;
if (created != asString)
{
var alert = new NSAlert()
{
AlertStyle = NSAlertStyle.Critical,
InformativeText = "That is incorrect, access is denied",
MessageText = "That is incorrect, access is denied",
};
alert.RunModal();
}
else if (ViewController.dtime == asString)
// This is where I am attempting to input the NSTextField, attempting to convert it to string called dtime.
{
byte[] textbytes = Convert.FromBase64String(encrypted);
AesCryptoServiceProvider endec = new AesCryptoServiceProvider();
endec.BlockSize = 128;
endec.KeySize = 256;
endec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
endec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
endec.Padding = PaddingMode.PKCS7;
endec.Mode = CipherMode.CBC;
ICryptoTransform icrypt = endec.CreateDecryptor(endec.Key, endec.IV);
byte[] enc = icrypt.TransformFinalBlock(textbytes, 0, textbytes.Length);
icrypt.Dispose();
if (ViewController.verify == created)
{
return System.Text.ASCIIEncoding.ASCII.GetString(enc);
}
else if (ViewController.verify != created)
{
var alert = new NSAlert()
{
AlertStyle = NSAlertStyle.Critical,
InformativeText = "It looks like you are trying to fool me by using a key file that was not created for this message. Nice Try.",
MessageText = "It looks like you are trying to fool me by using a key file that was not created for this message. Nice Try.",
};
alert.RunModal();
}
}
return encrypted;
}
Any thoughts are appreciated, than you.
Related
I'm trying to verify a webhook from bamboohr. the documentation is here https://documentation.bamboohr.com/docs/webhooks
and after unpacking the headers I see this:
X-BambooHR-Signature: 362cb0eff0193af8d3f939349f84014e5c70bba4cfc105682b45ecd305db01ff
X-BambooHR-Timestamp: 1652747163
Here is my code, from an azure function triggered by the webhook. The testOutput is not whats in the ‘X-BambooHR-Signature’ header:
string data;
using (var reader = new StreamReader(req.Body))
{
data = await reader.ReadToEndAsync();
}
string privateKey = "<gotten from bamboohr webhookconfig>";
if (req.Headers.Keys.Contains("X-BambooHR-Signature") && req.Headers.Keys.Contains("X-BambooHR-Timestamp"))
{
string timestamp = req.Headers["X-BambooHR-Timestamp"];
string signature = req.Headers["X-BambooHR-Signature"];
byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKey);
byte[] combinedBytes = Encoding.UTF8.GetBytes(data + timestamp);
HMACSHA256 hmac = new HMACSHA256(privateKeyBytes);
byte[] testOutputBytes = hmac.ComputeHash(combinedBytes);
string testOutput = Convert.ToBase64String(testOutputBytes);
log.LogInformation("testOutput is: " + testOutput); //----NOT EQUAL TO signature.
}
Any idea what I might be doing wrong? the testUutput is something like 'llBdZd2IfVdrJBlkGFFNG2dszDxpgJlJ4vQqTATJsYU=' which as you can see isnt even close.
Instead of using ToBase64String, try converting it to hexadecimal format. (There are different ways to convert it.) I had similar issue verifying bambooHR signature key in python, and fixed it by converting expected signature to hexadecimal format (not bytes or bytes string).
c#
using System;
using System.Text;
using System.Security.Cryptography;
namespace Test
{
public class VerifySignature
{
public static void Main(string[] args)
{
string data = "request data";
string privateKey = "your private key";
string timestamp = "1652747163";
string signature = "362cb0eff0193af8d3f939349f84014e5c70bba4cfc105682b45ecd305db01ff";
byte[] privateKeyBytes = Encoding.UTF8.GetBytes(privateKey);
byte[] combinedBytes = Encoding.UTF8.GetBytes(data + timestamp);
HMACSHA256 hmac = new HMACSHA256(privateKeyBytes);
byte[] testOutputBytes = hmac.ComputeHash(combinedBytes);
// edited from here
// string testOutput = Convert.ToBase64String(testOutputBytes);
// log.LogInformation("testOutput is: " + testOutput);
string hexOutput = BitConverter.ToString(testOutputBytes).Replace("-",""); // convert to hexadecimal format
Console.WriteLine(hexOutput);
}
}
}
python
import hmac
from hashlib import sha256
def verify_signature(request):
received_signature = 'get sig from request headers'
timestamp = 'get timestamp from request headers'
private_key = 'your private key'
body = request.body
calculated_signature = hmac.new(
private_key, body + timestamp, sha256
).hexdigest()
return received_signature == calculated_signature
I hope this helps although it's a bit late!
I need to generate a HMAC-SHA256 hash in a PCL (developing for Xamarin Forms) which doesn't support the .NET built-in HMAC/cryptography classes, so I'm working with BouncyCastle to implement my cryptography classes.
I need to generate a HMAC-SHA256 hash, but I haven't been able to find any example on Google, nor does BouncyCastle seem to have any documentation for this. Can anyone help me out?
Thanks to the solution here I came up with this code:
public class HmacSha256
{
public byte[] Hash(string text, string key)
{
var hmac = new HMac(new Sha256Digest());
hmac.Init(new KeyParameter(Encoding.UTF8.GetBytes(key)));
byte[] result = new byte[hmac.GetMacSize()];
byte[] bytes = Encoding.UTF8.GetBytes(text);
hmac.BlockUpdate(bytes, 0, bytes.Length);
hmac.DoFinal(result, 0);
return result;
}
}
Corresponding unit test (uses FluentAssertions):
[TestClass]
public class HmacSha256Tests
{
private readonly HmacSha256 _hmac = new HmacSha256();
[TestMethod]
public void Hash_GeneratesValidHash_ForInput()
{
// Arrange
string input = "hello";
string key = "test";
string expected = "F151EA24BDA91A18E89B8BB5793EF324B2A02133CCE15A28A719ACBD2E58A986";
// Act
byte[] output = _hmac.Hash(input, key);
string outputHex = BitConverter.ToString(output).Replace("-", "").ToUpper();
// Assert
expected.Should().Be(outputHex);
}
}
Using this PCL offshoot of BouncyCastle https://www.nuget.org/packages/BouncyCastle-PCL/1.0.0.6 it's really easy, in fact identical to the windows api.
public string ComputeHMAC(string message)
{
var keyBytes = Encoding.UTF8.GetBytes(Constants.API_KEY);
var messageBytes = Encoding.UTF8.GetBytes(message);
var hmac = new HMACSHA256(keyBytes);
byte[] result = hmac.ComputeHash(messageBytes);
return Convert.ToBase64String(result);
}
And a unit test using the actual .Net version:
[Test, AutoMoqData]
public void Hash_Algorithm_Correct (
[NoAutoProperties] HashMacService sut,
string message)
{
string expected;
var key = Encoding.UTF8.GetBytes(Constants.API_KEY);
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
expected = Convert.ToBase64String(hash);
}
var result = sut.ComputeHMAC(message);
Assert.That(result, Is.EqualTo(expected));
}
I was using PCLCrypto but it kept crashing on Xamarin iOS, this was much cleaner and could be unit tested, wheras PCLCrypto required the platform apis so had to be deployed to a device.
private static void CreateToken(string message, string key)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[]keyByte = encoding.GetBytes(key);
HMACSHA256 hmacsha = new HMACSHA256(keyByte);
byte[]messageBytes = encoding.GetBytes(message);
byte[]hashmessage = hmacsha.ComputeHash(messageBytes);
Console.WriteLine(ByteToString(hashmessage));
}
public static string ByteToString(byte[]buff) {
string sbinary = "";
for (int i = 0; i < buff.Length; i++) {
sbinary += buff[i].ToString("X2"); // hex format
}
return (sbinary);
}
Above code saved my time while working for HMAC-SHA256, I hope this may help someone and here is the reference in detail http://billatnapier.com/security01.aspx
I am working in a MVC3 Project. Encryption and decryption method are working fine in locally, but when I put on live some values are not hitting. I found that the arithmetic symbols like +,/ cause the problem. How can I resolve this?
My code is given below:
RijndaelManaged aese = new RijndaelManaged();
public string Encrypt(string stringToEncrypt)
{
try
{
aese.Mode = CipherMode.CBC;
aese.Padding = PaddingMode.PKCS7;
aese.BlockSize = 128;
aese.KeySize = 128;
aese.Key = Encoding.UTF8.GetBytes("bsGCslxDSrPTesVG");
aese.IV = Encoding.UTF8.GetBytes("IkLNSuWfZaQdPQCS");
byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
ICryptoTransform crypto = aese.CreateEncryptor();
byte[] cipherText = crypto.TransformFinalBlock(inputByteArray, 0, inputByteArray.Length);
return (Convert.ToBase64String(cipherText));
}
catch
{
return "Encryption Error";
}
}
public string Decrypt(string stringToDecrypt)
{
byte[] inputByteArray = new byte[stringToDecrypt.Length + 1];
try
{
aese.Mode = CipherMode.CBC;
aese.Padding = PaddingMode.PKCS7;
aese.BlockSize = 128;
aese.KeySize = 128;
aese.Key = Encoding.UTF8.GetBytes("bsGCslxDSrPTesVG");
aese.IV = Encoding.UTF8.GetBytes("IkLNSuWfZaQdPQCS");
inputByteArray = Convert.FromBase64String(stringToDecrypt);
ICryptoTransform decrypto = aese.CreateDecryptor();
byte[] plainText = aese.CreateDecryptor().TransformFinalBlock(inputByteArray, 0, inputByteArray.Length);
return Encoding.UTF8.GetString(plainText);
}
catch
{
return "Dycription Error";
}
}
Given you're working with a web project, I'm going to guess that you're passing Base64-encoded cipher-text as a URL or similar. Because Base64 data contains characters that are interpreted differently when treated as a URL (e.g. a + in a URL is interpreted as space), your data will be corrupted if you include Base64-encoded data in a URL verbatim.
If you intend to pass Base64 data in this way, you must correctly URL-encode it (e.g. using System.Web.HttpUtility.UrlEncode()) before including it in the URL.
There is a URL-safe version of Base64, which uses - (minus) for value 62 and _ (underline) for value 63. See RFC 4648, section 5 for details.
I need to sign the string with private Key using RSA phpseclib and then verify it in C# . I have seen many examples of how to encrypt in C# and decrypt in php, but none of how to sign string in php and verify in .NET.
here is php code:
include('Crypt/RSA.php');
$info = "Something";
$PrivateKey= "<RSAKeyValue><Modulus>3C5QWo4H+............"; //long string
$unsignedString = base64_encode($info);
$signedString = HashAndSignBytes($info, $PrivateKey);
file_put_contents('file.txt', $unsignedString."\n".$signedString);
function HashAndSignBytes($stringToSign, $Key) {
$rsa = new Crypt_RSA();
$rsa->loadKey($Key); // private key
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$signature = $rsa->sign($stringToSign);
return base64_encode($signature);
}
and here is my attempt to read the file and verify it in C#:
const string publicKey = #"<RSAKeyValue><Modulus>3C5QWo4H.....";
TextReader reader = new StreamReader(path, Encoding.ASCII);
var unsignedString = reader.ReadLine();
var signedString = reader.ReadLine();
reader.Close();
if (VerifySignedHash(unsignedString,signedString, publicKey)) {
//some code
}
private bool VerifySignedHash(string stringToVerify, string signedString, string publicKey)
{
var byteConverter = new ASCIIEncoding();
var dataToVerify = Convert.FromBase64String(stringToVerify);
var signedData = Convert.FromBase64String(signedString);
try
{
// Create a new instance of RSACryptoServiceProvider using the
// key from RSAParameters.
var rsaAlg = new RSACryptoServiceProvider();
rsaAlg.FromXmlString(publicKey);
// Verify the data using the signature. Pass a new instance of SHA1CryptoServiceProvider
// to specify the use of SHA1 for hashing.
return rsaAlg.VerifyData(dataToVerify, new SHA1CryptoServiceProvider(), signedData);
}
catch (CryptographicException e)
{
Console.WriteLine(e.Message);
return false;
}
}
verfication fails...
In your "signing" code, you base64encode the original string, then write that string to the output file. However, on the C# side, you read that value into unsignedString, but never reverse the base64 encoding.
The end result is that you're trying to verify the bytes of the base64Encoded string, not the data itself, so the VerifyData step fails.
Think that's your problem.
Modifying the following line might solve the problem:
var dataToVerify = Convert.FromBase64String(stringToVerify);
I've been working over the last few days on trying to port the simple encryption (found here) used to log into the Wizards of the Coast Character Builder API (so my app can download a user's characters directly from the servers) to something I can use in a Windows 8 Metro app, since AesManaged didn't make it into the Metro cryptography libraries. Seeing as I'm a novice programmer at best, this has proven a bit beyond my skills.
Here's the code I need to port over:
public static byte[] SimpleEncrypt(string value, string key)
{
byte[] buffer2;
ICryptoTransform transform = GetSimpleAlgorithm(key).CreateEncryptor();
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write))
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
stream2.Write(bytes, 0, bytes.Length);
stream2.Flush();
stream2.FlushFinalBlock();
stream.Position = 0L;
buffer2 = stream.ToArray();
}
}
return buffer2;
}
private static SymmetricAlgorithm GetSimpleAlgorithm(string key)
{
AesManaged aes = new AesManaged();
byte[] source = new SHA256Managed().ComputeHash(Encoding.UTF8.GetBytes(key));
return new AesManaged { Key = source, IV = source.Take<byte>((aes.BlockSize / 8)).ToArray<byte>() };
}
This is used to encrypt the password prior to passing the login:
contentClient.Login(username, SimpleEncrypt(password, username));
And in case it's needed, the web service is located at: http://ioun.wizards.com/ContentVault.svc
In the comments on that link way up there in the first link, someone suggested some code for Windows 8 back in February, but said code had a few problems I had to fix before it would even compile, and even then, when I try to log in with it, I get an exception back from the service saying "padding is invalid and cannot be removed".
Here's what I'm currently working with:
private static byte[] SimpleEncrypt(string value, string key)
{
var simpleAlgorithm = GetSimpleAlgorithm(key);
var encryptedBuffer = CryptographicEngine.Encrypt(simpleAlgorithm.Item1, CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8), simpleAlgorithm.Item2);
var result = new byte[encryptedBuffer.Length];
CryptographicBuffer.CopyToByteArray(encryptedBuffer, out result);
return result;
}
private static Tuple<CryptographicKey, IBuffer> GetSimpleAlgorithm(string key)
{
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var keyAsBinary = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
var source = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256).HashData(keyAsBinary);
var shortKey = CryptographicBuffer.CreateFromByteArray(UTF8Encoding.UTF8.GetBytes(key).Take((int)provider.BlockLength).ToArray());
return new Tuple<CryptographicKey,IBuffer>(provider.CreateSymmetricKey(source), shortKey);
}
Any help getting this working would be EXTREMELY appreciated.
Welp, spent more time looking it over, and figured out the problem.
The suggested updated version was using the "key" string to create the IV, whereas it should have been using the hash of the key, instead.
Here's the functional version, in case anyone wants it:
private static byte[] SimpleEncrypt(string value, string key)
{
var simpleAlgorithm = GetSimpleAlgorithm(key);
CryptographicKey encryptKey = simpleAlgorithm.Item1;
IBuffer IV = simpleAlgorithm.Item2;
var encryptedBuffer = CryptographicEngine.Encrypt(encryptKey, CryptographicBuffer.ConvertStringToBinary(value, BinaryStringEncoding.Utf8), IV);
var result = new byte[encryptedBuffer.Length];
CryptographicBuffer.CopyToByteArray(encryptedBuffer, out result);
return result;
}
private static Tuple<CryptographicKey, IBuffer> GetSimpleAlgorithm(string key)
{
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var keyAsBinary = CryptographicBuffer.ConvertStringToBinary(key, BinaryStringEncoding.Utf8);
var source = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256).HashData(keyAsBinary);
byte[] sourceArray = new byte[source.Length];
CryptographicBuffer.CopyToByteArray(source, out sourceArray);
var shortKey = CryptographicBuffer.CreateFromByteArray(sourceArray.Take((int)provider.BlockLength).ToArray());
return new Tuple<CryptographicKey,IBuffer>(provider.CreateSymmetricKey(source), shortKey);
}