I need to create the same results when using Crypt::Encrypt('secret') from Laravel, in C#.
I found this thread Rijndael 256 Encrypt/decrypt between c# and php?
and it seemed to be what I need, but I'm having some trouble with the third argument the, initialization vector :(.
Laravel using Rijndael AES to encrypt the data. All the user has to input is a secret key, in the config folder, that is totally random and 32 characters long.
The encyrption method looks like this:
public function encrypt($value)
{
$iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
$value = base64_encode($this->padAndMcrypt($value, $iv));
// Once we have the encrypted value we will go ahead base64_encode the input
// vector and create the MAC for the encrypted value so we can verify its
// authenticity. Then, we'll JSON encode the data in a "payload" array.
$mac = $this->hash($iv = base64_encode($iv), $value);
return base64_encode(json_encode(compact('iv', 'value', 'mac')));
}
The full Encryptor.php can be found here: http://pastebin.com/yfWLPxGn
Any idea as to what I would have to input to get the same results? :)
Initialization vector is an input that is typically random. So, algorithm always creates a different value using the same input, key and the different IV. If you'd like to generate same result using both PHP and C# code, you need to use the same IV value.
Laravel's encrypt() does not return the encrypted value only. The value encrypt() generates a base64 encoded string which has json encoded values of iv, mac and encrypted value.
So the steps you need to apply in your C# encode() method:
Encode the string using the code in the link you gave.
base64_encode() the encrypted value. We will use this value in the further steps.
Create MAC (Message Authentication Code) using base64_encoded IV as the value, encrypted value as the key and sha256 as the algorithm. Take a look at this one
Now we have encrypted value, mac and iv.
Create a json string like this:
{
iv: iv value (base64 encoded),
value: encrypted value (base64 encoded),
mac: mac value created in 3rd step
}
base64 encode your this json string.
You're all set.
You would want to not apply padding and not apply any specific mode of operation. There is a pseudo-mode called ECB which basically applies the bare cipher over many blocks and applies no padding. It requires full blocks to be used.
If you don't have a full block to encrypt, you need to figure out what padding mode is used.
If that doesn't work, then you need to figure out what mode and what initialization vector is used. An initialization vector is usually prepended to a message as a unique value that varies per message, as a way to prevent some mathematical attacks on bare ciphers applied over many blocks.
Related
I have many different string values in a collection.
Some values were encrypted by X509Certificate2. All other values are numbers, non encrypted strings, dates, etc.
My goal to filter possible candidates for decryption. So I want to use a function that can implement first fast filtration of values that were encrypted.
I use this simple check:
private bool IsEncryptedValue(string value)
{
var result = !string.IsNullOrEmpty(value) && IsBase64String(value);
return result;
}
Please advise more correct (more strong) rules for checking encrypted value.
Thanks for any suggestions.
Ciphertext of any modern cipher is binary. If the ciphertext is in a string I would expect that it has been encoded using base 64 (or a dialect) or hexadecimals. Once you've decoded that it should be exactly be the key size if direct RSA encryption has been used. If a hybrid cryptosystem has been used then it should be at least the key size.
Of course, you will have to find out which RSA encryption scheme was used, and in the case of hybrid encryption you'd have to find out which symmetric encryption scheme was used as well. It might be that the encryption uses a known container format such as CMS or PGP, so you could scan for that as well.
Finally, although it is unlikely: in principle the outcome of RSA encryption is a number. If that number is stored in decimals then it should have keysize / 3.32192809 or fewer digits.
In principle the outcome of a cipher is randomized, so we don't have much to separate it from any other encoding. You can try and validate that it is randomized, but if you've only a small ciphertext then estimating the amount of randomness is relatively tricky - so I've not included that in my answer.
This is a strange endeavor though, generally you'd know if something is a ciphertext or not.
For a project I need to generate a SHA256 encrypted string in C#.
The requirements are Key: todaysDate and Value: "exampleString".
How can i realize that in C#? As far as I see the SHA256-Class does not contain a property for key in C#.
SHA256 isn't an encryption algorithm, it's a hash algorithm. In other words, it's a one way function whose job is to take an input of any length and produce an output of fixed length with low collisions that's always the same for the same input. Thus, it doesn't receive a key as an input because the nature of hashing is quite different from that of encryption.
If you want to encrypt something with a key and later decrypt it by having the same key, look into symmetric encryption like AES (e.g. using the AesManaged class).
You should do your own homework. If we do it for you, you learn nothing.
Also, as Theodoros mentioned, SHA256 is a hash, not encryption. A hash is a cryptographic checksum that is used to validate or compare data. It can not be reversed into the original plaintext, which is a requirement of encryption.
How can i realize that in C#? As far as I see the SHA256-Class does not contain a property for key in C#.
Either you or the person who gave you the assignment doesn't understand what is being asked.
SHA256 doesn't have a key or a value, it only has data going in and a hash coming out. No matter how much data you run through it, the size of the hash does not change, although it's value does. You can think of a hash as a fingerprint for a particular dataset.
Maybe something like this:
public static string sha256_hash(string sValue) {
StringBuilder oResHash = new StringBuilder();
using (SHA256 oHash = SHA256Managed.Create()) {
Encoding oEnc = Encoding.UTF8;
byte[] baResult = oHash.ComputeHash(oEnc.GetBytes(sValue));
foreach (byte b in baResult)
oResHash.Append(b.ToString("x2"));
}
return oResHash.ToString();
}
Probably I have several misunderstandings.
AFAIK signing a byte array with RSA-SHA1 generates a byte array (signature) of the same lenght as the RSA key used. Is that right?
From another side signing, roughly means generate a hash using SHA1 (so it is 160 bites long) and then with or without a padding scheme encrypt it with the private key.Is that right?
Later on, in order to recover this hash (with or without padding schema on it) I would need to encrypt the signature with the public key. Is that right?
Something is broken in my logic because I'm not able to encrypt the signature with the public key.
Or my code is wrong. I'm using .net RSACryptoServiceProvider and it raises a bad data length error when trying to encrypt a signature... I assume encrypt means apply RSA using public key, right?
When trying to decrypt it raises a Key Not found exception. As expected because I only have the public key.
EDIT:
Given a byte array and RSACryptoServiceProvider I could Encrypt, Decrypt and SignData. I thought that SignData (without padding schema to simplify the question) is a shortcut of apply SHA, then Decrypt. For Encrypt I mean applying the RSA formula using public key as input, and for Decrypt I mean applying the RSA formula (the very same formula) using private key as input. Are this definitions ok?
EDIT2:
For exemple have a look at the next signed xml: http://www.facturae.gob.es/formato/Versiones/factura_ejemplo2_32v1.xml
And the next powershell script:
$signb64="oYR1T06OSaryEDv8VF9/JgWmwf0KSyOXKpBWY4uAD0YoMh7hedEj8GyRnKpVpaFanqycIAwGGCgl vtCNm+qeLvZXuI0cfl2RF421F8Ay+Q0ani/OtzUUE49wuvwTCClPaNdhv2vfUadR8ExR7e/gI/IL 51uc3mEJX+bQ8dxAQ2w=";
$certB64="MIIDtDCCAx2gAwIBAgICAIcwDQYJKoZIhvcNAQELBQAwcjELMAkGA1UEBhMCRVMxDzANBgNVBAgT Bk1hZHJpZDEPMA0GA1UEBxMGTWFkcmlkMQ4wDAYDVQQKEwVNSVR5QzEbMBkGA1UECxMSTUlUeUMg RE5JZSBQcnVlYmFzMRQwEgYDVQQDEwtDQSB1c3VhcmlvczAeFw0wOTEwMTUxNjA5MzRaFw0xMDEw MTUxNjA5MzRaMHExCzAJBgNVBAYTAkVTMQ8wDQYDVQQIEwZNYWRyaWQxDzANBgNVBAcTBk1hZHJp ZDEOMAwGA1UEChMFTUlUeUMxGzAZBgNVBAsTEk1JVHlDIEROSWUgUHJ1ZWJhczETMBEGA1UEAxMK VXN1YXJpbyA1NDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAroms65axKuQK18YDfD/x6DIn 0zKZ+6bv1K2hItJxel/JvU3JJ80/nY5o0Zbn+PrvlR2xF3poWYcPHLZpesgxhCMfnP7Jb5OUfceL g44m6T9P3PG1lSAZs3H6/TabyWGJy+cNRZMWs13KnB9fDAjJ5Jw0HVkwYNwmb1c7sHCuyxcCAwEA AaOCAVgwggFUMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMB0GA1UdDgQWBBTYhqU2tppJoHl+S1py BOH+dliYhzCBmAYDVR0jBIGQMIGNgBT1oWqod09bsQSMp35I8Q6fxXaPG6FypHAwbjEPMA0GA1UE CBMGTWFkcmlkMQ8wDQYDVQQHEwZNYWRyaWQxDjAMBgNVBAoTBU1JVHlDMRswGQYDVQQLExJNSVR5 QyBETkllIFBydWViYXMxEDAOBgNVBAMTB1Jvb3QgQ0ExCzAJBgNVBAYTAkVTggEDMAkGA1UdEQQC MAAwNgYDVR0SBC8wLYYraHR0cDovL21pbmlzdGVyLThqZ3h5OS5taXR5Yy5hZ2UvUEtJL0NBLmNy dDA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vbWluaXN0ZXItOGpneHk5Lm1pdHljLmFnZS9QS0kv Y3JsLmNybDANBgkqhkiG9w0BAQsFAAOBgQAhAN/KVouQrHOgd74gBJqGXyBXfVOeTVW+UTthhfCv DatXzTcrkYPQMfBAQMgGEa5KaQXcqKKhaoCUvrzFqE0HnAGX+ytX41oxZiM2fGNxRZcyUApLEX67 m8HOA/Cs2ZDlpU2W7wiOX5qr+ToTyfXsnRwPWvJ8VUmmXwyMEKcuzg==";
$signb=[System.Convert]::FromBase64String($signB64);
$certb=[System.Convert]::FromBase64String($certB64);
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList #(,$certb)
$rsacsp = [System.Security.Cryptography.RSACryptoServiceProvider] $cert.PublicKey.Key;
$signb.Length*8;
$rsacsp;
$rsacsp.Encrypt($signb,0);
I tried:
$rsacsp.Encrypt($signb,[System.Security.Cryptography.RSAEncryptionPadding]::Pkcs1);
instead of
$rsacsp.Encrypt($signb,0);
But I always get a bad length error:
Exception calling "Encrypt" with "2" argument(s): "Bad Length.
EDIT 3:
After reading, I can see my main issue was "From another side signing, roughly means generate a hash using SHA1 (so it is 160 bites long) and then with or without a padding scheme encrypt it with the private key.Is that right?".
RSA sign (with a n bits key length) could be viewed as an operation that takes an arbitraty byte array and outputs n bits. In order to do that, it uses a hash function like SHA1 that takes an arbitrary byte array and produces a fixed output (160 bits for SHA1). Now in theory I could "encrypt" with the private key but then the output would be 160 bits long too it is not the way RSA is implemented. RSA Signing needs to apply padding function after the hash in order to produces an n bits text before "encrypting" it.
Another source of confusion is the meaning of the Encrypt method of .NET RSACryptoProvider. It turns out that this method has two parameters: a byte array and a flag indicating the padding function. It takes the byte array, applies the padding and then "encrypts" with the public key. It is of no use for a signature scenario. The operations decrypt and encrypt in RSACryptoProvider are not simmetrical. You can "decrypt" whatever has been "encrypt", but not the other way around.
At the end the confusion lies in that "atomic" functions used when encrypting/decrypting and the ones used when signin are the same, but they are used in incompatible ways.
AFAIK signing a byte array with RSA-SHA1 generates a byte array (signature) of the same lenght as the RSA key used. Is that right?
Usually yes, although the size will of course be encoded as octet stream (aka byte array) it is possible that the size of the signature is actually up to 7 bits larger. The key size is normally a multiple of 8 (bits) so this doesn't come up much.
From another side signing, roughly means generate a hash using SHA1 (so it is 160 bites long) and then with or without a padding scheme encrypt it with the private key.Is that right?
No, you should never perform modular exponentiation in RSA without padding; a padding scheme is required for security. Note that you should not talk about encryption here. Encryption is used to provide confidentiality. That RSA signature generation and encryption both uses modular exponentiation - although with different keys - doesn't mean one equates the other.
It is important to note that the padding scheme for PKCS#1 v1.5 encryption is different from the one used for signature generation. Furthermore there are also the newer OAEP padding scheme for encryption and the PSS padding scheme for signature generation which are rather distinct.
Later on, in order to recover this hash (with or without padding schema on it) I would need to encrypt the signature with the public key. Is that right?
Perform modular exponentiation and then verify the result, yes. But as the verification requires verifying the padding in a secure way you should really let an API handle this.
Something is broken in my logic because I'm not able to encrypt the signature with the public key.
Try something written for verification instead, like the method VerifyHash as seen in this example.
You can try and find a raw RSA implementation to find out what is within the RSA signature. You should only do this to analyze the signature.
So if you "encrypt" the data with the public key (i.e. just perform modular exponentiation) you would get:
0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff003021300906052b0e03021a05000414a2304127e2fe3b8a8203b219feafdd9b58558310
as result. This is clearly PCKS#1 v1.5 padding for signature generation. It includes an encoded hash value:
SEQUENCE(2 elem)
SEQUENCE(2 elem)
OBJECT IDENTIFIER1.3.14.3.2.26
NULL
OCTET STRING(20 byte) A2304127E2FE3B8A8203B219FEAFDD9B58558310
I am trying to do AES Encryption in my windows phone8 app.
I searched a lot, but couldn't get a clear view to do so.
Can anybody give me link that gives the clear example of implementing AES Encryption ni WP8 App.
What i need to do is,
1)I need to pass key, initial vector, and value as strings.
2)need to encrypt that string in any format of AES Encryption, and finally need to get the encrypted value as string.
Can anybody help me.
am using this example and using UTF8 encoding for key, and Iv
myAes.Key = Encoding.UTF8.GetBytes("terr!f!cp#ssw0rdw!thonetw!st!n!t");
myAes.IV = Encoding.UTF8.GetBytes("1234567890987654");
and after encoding to convert the bytes of encrypted value to string am using ToBase64 convertion
afterText.Text = Convert.ToBase64String(encrypted);
here i need to tell my back end team, what the exact encryption am using here, am not sure about what is happening here, Can you please tell me whats that exact encryption happening here.
Thank you.
The CryptographicBuffer Class is your friend:
Use Hex or Base64 encoding for binary values you want to represent as strings. This includes Key, IV and ciphertext
Use UTF-8 for text you want to turn to bytes.
I have an API that decrypts data. This API receives only key (bytes of an AES key). This API does not receive initialization vector (It uses vector of zeros as an initialization vector).
I'm receiving from 3rd party an encrypted data. This data was encrypted to AES 256 using a specific key and initialization vector.
I have the key and the initialization vector. Is there a way to decrypt this data using the API? or, in other words, if the key and the initialization vector are constants and I have them both, can I create a key that will allow me to decrypt this data with a {0, 0, 0, ...} initialization vector?
Thanks.
Yes it is possible to decrypt ... no not the way you described
AES is a block cipher
most of the time the cipher isn't used as it is, but it is put into a special mode of operation (this is what your API probably is not capable of)
you will have to implement the decryption routine around the cipher and use your AES-API just as a crypto-primitive
for example, the decryption of AES-CBC using a generic AES implementation
split ciphertext into 128 bit blocks and number them from index 1 onward
prepend the IV as cypher_block 0
now to obtain the plaintext we can define a function around your API function
plaintext_block[i] = cypher_block[i-1] XOR aes_decrypt(cypher_block[i],key)
as you can see, you can obtain all plaintext blocks from index 1 onward ...
once you have obtained all plaintext blocks you will probably want to strip padding, but that's another story ...