I am working on a code
if (!function_exists('decrypt_password')) {
function decrypt_password( $iv, $value)
{
$key = config('services.decrypt.key');
$string_iv =hex_to_string($iv);
$encrypter = new Encrypter($key, 'AES-256-CBC');
$dec['iv'] = base64_encode($string_iv);
$dec['value'] = $value;
$dec['mac'] = hash_hmac('sha256', $dec['iv'] . $dec['value'], $key);
return ($encrypter->decrypt(base64_encode(json_encode($dec)),false));
}
}
this piece of code should make a layer of decrypting the password, and key is missing in config and I can't get one or generate a new one.
any help!
edit: I tried to set 32 char key like "22222222222222222222222222222222" and got a new error The payload is invalid
The problem was in decrypt the logic should encrypt.
Related
I have the following decrypted message, which has previously been encrypted using AES-256-CBC
240dcbefc0f82fadc00ef8494488aaa81400000c2def01e79fec6c4d9a822358dd8a910cac606e8afcb607793cb442093a56b7b40b0b0b0b0b0b0b0b0b0b0b0b
I derive the following 20 BYTE HMAC from this message:
dd8a910cac606e8afcb607793cb442093a56b7b4
My goal is to re-create this HMAC using PHP, I attempt with the following code:
$iv = hex2bin('240dcbefc0f82fadc00ef8494488aaa8'); // random iv - first 16 bytes of the message
$message = hex2bin('1400000c2def01e79fec6c4d9a822358'); // the actual message being decrypted - next 16 bytes
$key = hex2bin('b109124b62e2c8b8248e9865990325fddcc61143'); // encryption key
$hmac = hash_hmac('sha1', $iv.$message, $key);
print($hmac); // 03634ba3f4a0c854a0b791d27f331ecdfad1e87e
$attempt2 = hash('sha256', $iv.$message, true);
$hmac = hash_hmac('sha1', $attempt2, $key);
print($hmac); // 39ad1fb94ab251cdaf3f21cf8673e070733f4e16
I know I'm missing something but I'm struggling to understand the HMAC process as it's very confusing to me. Any help or advise is appreciated, thanks.
I found a solution on a random blog post online :D
here is what worked for me:
function check_mac($seq, $type, $msg, $key) {
$SequenceNumber = pack("NN", 0, $seq);
$Type = pack("Cnn", $type, 0x0303, strlen($msg));
$data = $SequenceNumber . $Type . $msg;
$calculated_mac = hash_hmac("sha1", $data, $key, true);
print(bin2hex($calculated_mac) . "\n");
}
Also, the IV does not need to be included, just the message by itself as the $msg variable
Blog Post:
https://adayinthelifeof.nl/2013/12/30/decoding-tls-with-php/
I'm trying to encrypt a message using phpseclib. Below is the method that encrypts it:
function RSAEncrypt($data, $publicKey)
{
$rsa = new \Crypt_RSA();
$rsa->loadKey($publicKey);
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$encryptedData = $rsa->encrypt($data);
$encodedData = base64_encode($encryptedData);
return $encodedData;
}
the code that encrypt message
$client_key = 123456789;
$random_str = rand();
$aes_password = $client_key.'-'.$random_str;
$public_key = file_get_contents('keys/public.xml');
$ecrypted_password = RSAEncrypt($aes_password, $public_key);
but no matter the message the $aes_password that i passed , the $ecrypted_password output is always
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE= ◀"
I tried to decrypt it using the private key to see if its valid anyways but i always gets Decryption Error so i figured maybe the error is with the encryption
I am trying to verify a signature in php, and have exhausted myself trying every example I have found on the net. I've gone round in circles so much I have probably missed the solution now.
So I have test data which is
$msg = "test data";
which produced this signature using the private key from my key pair
$signature = "avALtk00btVyV74e5UdXJ/VClVV/fsuoLZpXQjiCrkVijsmMZsYWZujN56+Aa2CEQYkomDsm9CJ/Tue7lNP0tYVZz9Y0RngpcV9VT9V3i+3rbvbBEnuJuS/5e+PR7kQGMh8rVuCtHpAJhSePMyipC3kM90EQJ0jyY3rFaHDNpSzVBpOnRYLzqbsdy45v0bN78A2J/HaIhJy87Sh4X1a+WMg9PLkqSSYZnRYOB8XVDCYfyeeekcvI4rvP51wBQcaLwu7S0xPQA8yHfJqMXCqdmBVUQZrk/X+CujdXUyJItDWA8j2N8AHmcAD5oRaJ6bX3zCQFM1QnKMi1ETLudzIqfA==";
and this is the public key from the signing key pair
$key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxv4nCiH4vXvSLsvlceCOk3yfH1EQgNqNaVGdnFxdw9IIjSVZvTVH45NCodCJ0GlHoDwQM7DMV1+QrtF91cn44xg4Ys9zr1xkaT4jWBTe3YKoTqJoLHR4UU03F6Y1jTELhjY2a2Kt0ijyvAOKM4bm3gCItfMx59ETGInz7Oubb1T4IJ8TuWmZsh+X57c6fgv0B2+eTr/5FMK2VxXV5tHkB9UNLBgnbw0IZuC6izF4OFk9hxgh96i5wCf2HhHaNoEryx7ZV2ZG9a0OQnYZ+x1zaOIw6dJkV7rip3H57ksQfoQWM0GKMBB7cWIgWsf/GlbYTVgw26MvzEzGPb9uCfx8rwIDAQAB";
I have tried wrapping the key with this
$pubkey = "-----BEGIN RSA PUBLIC KEY-----" . $key . "-----END RSA PUBLIC KEY-----";
and with this
$pubkey = "-----BEGIN PUBLIC KEY-----" . $key . "-----END PUBLIC KEY-----";
I have tried creating a public key id with both wrappings and without any wrapping, like this
$pubkeyid = openssl_pkey_get_public($pubkey);
$pubkeyid = openssl_pkey_get_public($key);
and I have tried verifying the signature with $key and $pubkeyid, with various algorithms and with none, like this
openssl_verify($msg, base64_decode($signature), $pubkeyid);
openssl_verify($msg, base64_decode($signature), $key);
openssl_verify($msg, base64_decode($signature), $pubkeyid, "sha256withRSAEncryption");
openssl_verify($msg, base64_decode($signature), $key, "sha256withRSAEncryption");
openssl_verify($msg, base64_decode($signature), $pubkeyid, OPENSSL_ALGO_SHA256);
openssl_verify($msg, base64_decode($signature), $key, OPENSSL_ALGO_SHA256);
I probably tried some other permutations, but can't remember now. My head hurts.
No matter what I tried, I have not managed to verify the signature. I can verify the signature using the public key in java easily.
I loathe asking for a working php example because I have tried so many I have already found on the net and just can't get them to work. Unfortunately phpseclib is not an option for me, so I have to use openssl.
Where am I going wrong?
Thanks to #miken32 I have now finally fixed the code. Turns out all I was missing was a couple of line breaks when formatting the PEM key. So the final, and very simple code is:
// Get base64 encoded public key.
// NOTE: this is just for testing the code, final production code stores the public key in a db.
$pubkey = $_POST['pubkey'];
// Convert pubkey in to PEM format (don't forget the line breaks).
$pubkey_pem = "-----BEGIN PUBLIC KEY-----\n$pubkey\n-----END PUBLIC KEY-----";
// Get public key.
$key = openssl_pkey_get_public($pubkey_pem);
if ($key == 0)
{
$result = "Bad key zero.";
}
elseif ($key == false)
{
$result = "Bad key false.";
}
else
{
// Verify signature (use the same algorithm used to sign the msg).
$result = openssl_verify($msg, base64_decode($signature), $key, OPENSSL_ALGO_SHA256);
if ($result == 1)
{
$result = "Verified";
}
elseif ($result == 0)
{
$result = "Unverified";
}
else
{
$result = "Unknown verification response";
}
}
// do something with the result.
Usually, I use openssl_encrypt to encrypt simple string with AES in PHP, and it works pretty well.
Now I need to encrypt files with AES-256-CTR mode, but the only way to do this is to file_get_contents the entire content of the file and then send it to the openssl_encrypt function to encrypt the actual file data. The problem is this method is very "poor" because of the critical waste of memory.
1) Is there a way to work with chunked data with PHP OpenSSL ?
For example:
<?php
// ...
$f = fopen('large.iso','r');
while(feof($f)){
$chunk = fread($f,16);
$cipher = openssl_encrypt(...$chunk...);
// ... code ...
}
// ... more code ...
?>
2) openssl_encrypt official documentation is not published yet. Does someone could clarify the meaning of the parameters of the function for use with AES-CTR mode? Does the counter is handled automatically? Is it necessary to apply a manual XOR the data returned by the function?
Note: It is a professional project so I don't want to use phpseclib or others' "anonymous" libraries, nor do I don't want to use the command line as well.
Looks like for php it's not possible to use aes-256-ctr without temporary file.
But for next chiper types:
OPENSSL_CIPHER_RC2_40
OPENSSL_CIPHER_RC2_128
OPENSSL_CIPHER_RC2_64
OPENSSL_CIPHER_DES
OPENSSL_CIPHER_3DES
OPENSSL_CIPHER_AES_128_CBC
OPENSSL_CIPHER_AES_192_CBC
OPENSSL_CIPHER_AES_256_CBC
you can use generating key on the fly:
$res = openssl_pkey_new('chiper args here');
openssl_pkey_export($res, $private_key);
$public_key = openssl_pkey_get_details($res);
$public_key = $public_key["key"];
Then encrypt:
$crypted_text = openssl_get_privatekey($private_key,'your data');
And decrypt:
openssl_public_decrypt($crypted_text,$decrypted_text,$public_key);
So if you don't want to use files, may be switching to OPENSSL_CIPHER_AES_256_CBC will help you?
1) It should be something like this:
function strtohex($x) {
$s = '';
foreach (str_split($x) as $c){
$s.=sprintf("%02X", ord($c));
}
return($s);
}
$method = "aes-256-ctr"; //aes-256-cbc
echo "Selected method: ".$method."<br /><br />";
$textToEncrypt = "My chunk of data";
$iv = "1234567890123456";
$pass = 'some_pass';
$dec_iv = strtohex($iv);
$key = strtohex($pass);
$enc_data = openssl_encrypt($textToEncrypt, $method, $pass, true, $iv);
echo "Encrypted message (openssl): ".$enc_data."<br />";
$dec_data = openssl_decrypt($enc_data, $method, $pass, OPENSSL_RAW_DATA, $iv);
echo "Decrypted message (openssl): ".$dec_data."<br />";
For CTR $iv should be unique for each chunk or your data can be broken.
2) I know only abot difference betwen CBC and CTR:
For CBC, the IV must be random, but not unique. It also must not be known.
For CTR, the IV must be unique and not known, but does not need to be random.
Hi i have c# sample of code but i can't turn it to php.
İ tried to rewrite code but i can't do it.
In my project other server encrypts data with c# and i have to decrypt it using PHP.
I have password and salt value.
Here is C# code includes encrypt and decrypt function.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace EncryptionSample
{
public static class CipherUtility
{
public static string Encrypt(string plainText, string password, string salt)
{
if (plainText == null || plainText.Length <= 0)
{
throw new ArgumentNullException("plainText");
}
if (String.IsNullOrEmpty(password))
{
throw new ArgumentNullException("password");
}
if (String.IsNullOrEmpty(salt))
{
throw new ArgumentNullException("salt");
}
byte[] encrypted;
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
using (Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(password, saltBytes))
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = derivedBytes.GetBytes(32);
aesAlg.IV = derivedBytes.GetBytes(16);
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
}
return Convert.ToBase64String(encrypted);
}
public static string Decrypt(string cipherValue, string password, string salt)
{
byte[] cipherText = Convert.FromBase64String(cipherValue);
if (cipherText == null
|| cipherText.Length <= 0)
{
throw new ArgumentNullException("cipherValue");
}
if (String.IsNullOrWhiteSpace(password))
{
throw new ArgumentNullException("password");
}
if (String.IsNullOrWhiteSpace(password))
{
throw new ArgumentNullException("salt");
}
string plaintext = null;
byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
using (Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(password, saltBytes))
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = deriveBytes.GetBytes(32);
aesAlg.IV = deriveBytes.GetBytes(16);
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
}
return plaintext;
}
}
}
My php code is here but i think i am totally wrong.
function decrypt($encrypted, $password, $salt) {
// Build a 256-bit $key which is a SHA256 hash of $salt and $password.
$key = hash('SHA256', $salt . $password, true);
// Retrieve $iv which is the first 22 characters plus ==, base64_decoded.
$iv = base64_decode(substr($encrypted, 0, 22) . '==');
// print_r($iv);die();
// Remove $iv from $encrypted.
$encrypted = substr($encrypted, 22);
//print_r($encrypted);die();
// Decrypt the data. rtrim won't corrupt the data because the last 32 characters are the md5 hash; thus any \0 character has to be padding.
$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($encrypted), MCRYPT_MODE_CBC, $iv), "\0\4");
// Retrieve $hash which is the last 32 characters of $decrypted.
$hash = substr($decrypted, -32);
// Remove the last 32 characters from $decrypted.
$decrypted = substr($decrypted, 0, -32);
// Integrity check. If this fails, either the data is corrupted, or the password/salt was incorrect.
if (md5($decrypted) != $hash) return false;
return $decrypted;
}
On first glance, I can see that your keys are going to be different. Your C# code generates your key using Rfc2898DeriveBytes, which is a key generator based on PBKDF2. Your php code, on the other hand, is using SHA256 to generate the key. These are going to return different values. With different keys, you are done before you even start.
Also, I don't know that CryptoStream is going to append the IV on the beginning of the ciphertext, nor a MAC value at the end of the ciphertext. Stripping out that text will make your plaintext garbled if it will decrypt at all. Note in the C# decryption method you derive the IV based on the key derivation object (which is not smart, since the same key will generate the same IV for every message, which reduces the security of the first block of your ciphertext, but that's an entirely separate issue).
Do you know for a fact that the C# server is generating the ciphertext exactly the same as your code sample? You need to know the exact parameters of the cryptography being used on the server side
I would suggest that you actually try to research and understand the format of the ciphertext that C# is going to emit, then figure out how to consume that in PHP. Cryptography can be very tricky to work with, especially when trying to integrate heterogenous systems.
I'm no crypto expert, but I think you might find phpseclib useful.