I am developing a private messaging system for my website using Laravel 4, and I want to ensure that the messages remain private. So far, I have the following code written:
class PkeyEncryption {
public static function encrypt($input, $cipher = MCRYPT_RIJNDAEL_128) {
$key = sha1(microtime(true) . mt_rand(10000, 90000));
$iv_size = mcrypt_get_size($cipher, MCRYPT_MODE_CFB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
return mcrypt_encrypt($cipher, $key, $input, MCRYPT_MODE_CFB, $iv);
}
public static function decrypt($data, $key, $cipher = MCRYPT_RIJNDAEL_128) {
$iv = $data['iv'];
$data = $data['data'];
return mcrypt_decrypt($cipher, $key, $data, MCRYPT_MODE_CFB, $iv);
}
}
So, I know how to encrypt the messages, and I also know that I can store the IV alongside the message. But, I don't know where I am supposed to store the public key. I have already read a few other questions on the site, and I still haven't found an answer. Can somebody please point me in the right direction?
You have to store all users public keys on the server and only the users themselves should have their own private keys.
When user A wants to send message to user B, he will take user B public key and encrypt the message with it. This message can then be decrypted only with the user B private key.
Related
I am sorry for my English.
The project migrates from Node to Laravel.
I'm the junior, maybe someone will tell me the right direction in the search)))
How to decrypt in Laravel what is encrypted in cryptojs?
In Node, they use CryptoJS and worked with passwords like this:
Encrypt
password: cryptojs.encrypt(JSON.stringify(req.body.password), secretKey).toString(),
Decrypt
cryptojs.decrypt(user.password.toString(), secretKey);
I'm trying to implement a password-checking mechanism in Laravel.
I have secretKey, old password, db stored data.
Tried this
$newEncrypter = new \Illuminate\Encryption\Encrypter(config('app.secret_key'), config('app.cipher'));
$decrypted = $newEncrypter->decrypt( $encrypted );
tinker output: Illuminate\Contracts\Encryption\DecryptException The payload is invalid.
Tried this and it return false
public function check($value, $hashedValue, array $options = [])
{
$hashedBytes = base64_decode($hashedValue);
$iv = substr($hashedBytes, 0, openssl_cipher_iv_length('aes-256-cbc'));
$encrypted = substr($hashedBytes, openssl_cipher_iv_length('aes-256-cbc'));
$decrypted = openssl_decrypt($encrypted, 'aes-256-cbc', $this->key, OPENSSL_RAW_DATA, $iv);
return $value === $decrypted;
}
I'm using PEAR::Mail to send a lot of e-mails to our customers. I want to be able to send those e-mails using different SMTP accounts (because of different mailing types). We have like 6-7 accounts, and in the future there might be more. Each of them has different password and we want to be able to store those passwords in database so it's not hardcoded and so you can add them more easily with administrator panel.
I know I want to use encryption for password storing, but imo hashing is not an option here. I want to be able to read those passwords, not only compare the hashes.
I would like to do it with storing encrypted passwords in database but encrypt them with some algorithm. And that's where I have problem - I don't know much about that. I'm attaching my test code for encryption, but I would like your opinion on how should I improve it:
if (!function_exists('hex2bin')) {
function hex2bin($data) {
$len = strlen($data);
return pack('H' . $len, $data);
}
}
$key = $_GET['key'];
$text = $_GET['text'];
$encr = $_GET['encr'];
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
if ($text != null) {
echo bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv));
}
if ($encr != null) {
echo mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, hex2bin($encr), MCRYPT_MODE_ECB);
}
ECB mode is insecure and the IV is ignored with this mode. You should really use CBC (MCRYPT_MODE_CBC) instead.
When using CBC an IV is required for encryption and the same IV is required for decryption, so you need to hang on to this value (but don't use the same IV for all encryption/decryption, generating a random one as in your code example is correct). The IV does not need to be stored securely (any more securely than the encrypted data), and it's standard proceedure to prepend the IV to the encrypted data.
bin2hex($iv . mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_CBC, $iv));
When decrypting you strip off the IV and pass it in to mcrypt_decrypt.
$cipherTextDecoded = hex2bin($encr);
$iv = substr($cipherTextDecoded, 0, $iv_size);
$cipherText = substr($cipherTextDecoded, $iv_size);
mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $cipherText, MCRYPT_MODE_CBC, $iv);
Also note that you should be using a binary key. $_GET['key'] is returning a string of text, and because you're not hex decoding it your keyspace is limited to all possible 256-bit strings rather than all 256-bit binary values.
Further, it's a bit misleading in PHP, but the 256 in MCRYPT_RIJNDAEL_256 refers to the block size, not the strength of the encryption. If you want to use 256 bit encryption, just pass a 256 bit key to the mcrypt functions. If that was your goal I'd consider using MCRYPT_RIJNDAEL_128 instead, this will make the encrypted text compatible with AES-128. If you ever need to decrypt the data in some other system (unlikely I know), it's much easier to find an AES-128 imeplementation than Rijindael 256.
I created a class which does everything what Syon mentioned. I'm attaching it here for future reference, if anyone would like to use it then feel free.
<?php
if (!function_exists('hex2bin')) {
function hex2bin($data) {
$len = strlen($data);
return pack('H' . $len, $data);
}
}
/**
* Encipherer - Class used for encoding and decoding
*
* #author kelu
* #version $Id$
*
*/
class Encipherer {
private $key;
private $iv_size;
private $mode = MCRYPT_MODE_CBC;
private $algorithm = MCRYPT_RIJNDAEL_256;
private $rand = MCRYPT_RAND;
/**
* returns singleton
*
* #return Encipherer
*/
public static function Instance()
{
static $inst = null;
if ($inst === null) {
$inst = new Encipherer;
}
return $inst;
}
private function __construct($key = '') {
$this->iv_size = mcrypt_get_iv_size($this->algorithm, $this->mode);
$this->key = $this->key = hex2bin($key);
}
private function __clone()
{
return Encipherer::Instance();
}
public function setKey($key) {
$this->key = $this->key = hex2bin($key);
}
public function encrypt($text) {
$iv = mcrypt_create_iv($this->iv_size, $this->rand);
return bin2hex($iv . mcrypt_encrypt($this->algorithm, $this->key, $text, $this->mode, $iv));
}
public function decrypt($text) {
$cipherTextDecoded = hex2bin($text);
$iv = substr($cipherTextDecoded, 0, $this->iv_size);
$cipherText = substr($cipherTextDecoded, $this->iv_size);
return mcrypt_decrypt($this->algorithm, $this->key, $cipherText, $this->mode, $iv);
}
}
?>
Example usage:
<?
$enc = Encipherer::Instance();
$enc->setKey('1234qwerty');
$encrypted = $enc->encrypt('secret message');
$decrypted = $enc->decrypt($encrypted);
?>
How can i decrypt a string which has been encrypted using the Laravel 4 Encrypt class, outside of Laravel, only with PHP?
The Laravel Encrypter class uses Rijndael with a block size of 256 bit for encryption which is provided by the Mcrypt PHP extension. The Encrypter class works using two simple methods, encrypt() and decrypt().
An example below:
<?php
$secret = Crypter::encrypt('some text here'); //encrypted
$decrypted_secret = Crypter::decrypt($secret); //decrypted
?>
Since you're asking how to do it "outside of Laravel":
The encryption and decryption is done by the encrypter class. Laravel source is public and here's the relevant part:
<?php
public function encrypt($value)
{
$iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
$value = base64_encode($this->padAndMcrypt($value, $iv));
$mac = $this->hash($iv = base64_encode($iv), $value);
return base64_encode(json_encode(compact('iv', 'value', 'mac')));
}
protected function padAndMcrypt($value, $iv)
{
$value = $this->addPadding(serialize($value));
return mcrypt_encrypt($this->cipher, $this->key, $value, $this->mode, $iv);
}
public function decrypt($payload)
{
$payload = $this->getJsonPayload($payload);
$value = base64_decode($payload['value']);
$iv = base64_decode($payload['iv']);
return unserialize($this->stripPadding($this->mcryptDecrypt($value, $iv)));
}
protected function mcryptDecrypt($value, $iv)
{
return mcrypt_decrypt($this->cipher, $this->key, $value, $this->mode, $iv);
}
?>
For documentation and comments, see Laravel source code on GitHub.
I hope this helps.
The Encrypter class of Laravel is prone to changes. This is due to some security vulnerabilities that got fixed. So to successfully decrypt you need to do the following things:
Get the right source code, e.g. for 4.2.16;
Get it to work on your machine. Make sure you run on the same PHP environment (using OpenSSL extensions for the latest versions);
Instantiate the class in Encrypter with the correct key, and possibly set the correct mode and algorithm;
Finally, call decrypt.
All other required parameters for decryption (IV and MAC value) should be contained within the ciphertext.
I am using a text
const ENCRYPTION_KEY = '3aa22e01c04c7059778c54d122b0273689fba00f4a166a66d15f7ba6a8ba8743';
$str = "1844427316My Name Is Dave1336407610774000000000000";
function encrypt($str){
trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,ENCRYPTION_KEY, $str,MCRYPT_MODE_CBC,mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),MCRYPT_RAND))));
}
function decrypt($encryptedtext){
return trim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
ENCRYPTION_KEY,
base64_decode($encryptedtext),
MCRYPT_MODE_CBC,
mcrypt_create_iv(
mcrypt_get_iv_size(
MCRYPT_RIJNDAEL_128,
MCRYPT_MODE_CBC
),
MCRYPT_RAND
)
)
);
}
But whenever I refresh the page calling these function with values mentioned above, I get different values encryption, but in decryption, the initial decrypted value changes everytime but rest gets decrypted correctly like wise:
F7…Ÿ{4©eŠQ9t¤e Is Dave1336407610774000000000000
I have also refered the SIMILAR QUESTION and used the "iv" function in decryption as well as answered in it
Could some one guide me whats getting wrong in here?
It was thoughtful But I found the Solution:
While decrypting, I used the same IV and key as when encrypting.
My encrypt function needs to return the IV as well as the encrypted data. That IV is sent to the decrypt function with the data and the key.
See the below Change in Code with complete code:
class Encypt{
const ENCRYPTION_KEY = '3aa22e01c04c7059778c54d122b0273689fba00f4a166a66d15f7ba6a8ba8743';
function createQueryString(){
$str = "1844427316My Name Is Dave1336407610774000000000000";
$encStr = $this->encrypt($str);
return $encStr;
}
function encrypt($strValue){
$iv =mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128,MCRYPT_MODE_CBC),MCRYPT_RAND);
$encData = trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,self::ENCRYPTION_KEY, $strValue,MCRYPT_MODE_CBC,$iv)));
$data['iv'] = $iv;
$data['encdata'] = $encData;
return $data;
}
/**
* Function to decrypt data using AES Encryption Symmetric Algorithm 128 bytes
*/
function decrypt($strValue, $iv){
return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,ENCRYPTION_KEY,base64_decode($strValue),MCRYPT_MODE_CBC,$iv));
}
}
$enc_obj = new Encypt();
$encstr = $enc_obj->createQueryString();
echo "Encrypted Str:-->".$encstr['encdata']."<br>";
$deCrypt = $enc_obj->decrypt($encstr['encdata'], $encstr['iv']);
echo "Decrypted Str:-->".$deCrypt;
Alright, I'm trying to encrypt files when they are uploaded onto a server. I've found code here at stackoverflow, but I'm having problems implanting it. I'm getting the error unexpected '(', expecting ',' or ';' in where/the/file/is.php. It's pointing to the const KEY = md5('somesecretcode'); line. I know that it's saying that it's expecting the end of the line after the md5, but I'm not sure why? You think it would accept the now "encrypted" string as a valid string. If need be, I'll upload some more code up hear. Thanks for your help in advance! I'm kind of new to this so please don't be too rough.
Here's the code
<?php
class Encryption
{
const CYPHER = MCRYPT_RIJNDAEL_256;
const MODE = MCRYPT_MODE_CBC;
const KEY = md5('somesecretcode');
public function encrypt($plaintext)
{
$td = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, self::KEY, $iv);
$crypttext = mcrypt_generic($td, $plaintext);
mcrypt_generic_deinit($td);
return base64_encode($iv.$crypttext);
}
public function decrypt($crypttext)
{
$crypttext = base64_decode($crypttext);
$plaintext = '';
$td = mcrypt_module_open(self::CYPHER, '', self::MODE, '');
$ivsize = mcrypt_enc_get_iv_size($td);
$iv = substr($crypttext, 0, $ivsize);
$crypttext = substr($crypttext, $ivsize);
if ($iv)
{
mcrypt_generic_init($td, self::KEY, $iv);
$plaintext = mdecrypt_generic($td, $crypttext);
}
return trim($plaintext);
}
}
?>
and I'm calling it like...
$encrypted_string = Encryption::encrypt('this is a test'); // Åž-\Ž“kcþ1ÿ4gî:Xƒã%
$decrypted_string = Encryption::decrypt($encrypted_string); // this is a test
You can't use function calls or arrays along with const. You will have to find another way to set the constant (or just hard code the value of md5('somesecretcode')).
You cannot use "const", because this gets parsed at compile time where function calls are not yet possible.
You can use define function like this
define('KEY', md5('somesecretcode'));
This is a function, gets executed at runtime and will work. You will have to place it somewhere where it can be executed - like class constructor for example.
But using define in this context is not a very good design, because then creating an instance of your class will write something into global (or into the namespace ) scope.
So you need to rethink your solution. If you insist on keeping static method calls, maybe pass the secret into the function as input parameter?
You should not use a function to init a const variable outside the constructor.
You can do instead:
class Encryption
{
const CYPHER = MCRYPT_RIJNDAEL_256;
const MODE = MCRYPT_MODE_CBC;
const KEY = '';
public function __construct(){
$this->KEY = md5('somesecretphrase');
}
...
Update:
This is NOT TRUE!
Even though this code seems to be working what it really does is creating another object member called KEY (even though it doesn't have the $ - which is kind of confusing) and assigning it with md5('somesecretphrase'). This member is not a constant and can be changed at any time.
The class member KEY which can be referred to by self::KEY remains empty!