I have a RSA Public key in base64_encoded form:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzkBJ/Wuyj0hZWa6oH+hD
+5JX1rV/TAf3lKxTPf0MUrREh2S3QPzLYBdUxByI552I3nAHJAh6JujUjGkj4O1y
X6OBJHJ596GQnv0wBUF5sr0QVg2ljav33HkuHt+otriY7jZy+OTlivkmdSdyhXht
VNlw+GgyQxeAI4f1BgaEGAfd9QJyN9yrkyZLqs9+CCmMog8ZbcqqSlR/S5nhUJku
zTD4YvmaA4okQADyOtktTCyUC3ndhRuGp451h+p5WAmcXYpW3QrqDfDzuFMy5Vlw
IB/EA9fZeMTY2tWi/7YnaVqYDJjhQv2XueOMizMCFCN2by+blc83uduPXJQpXHrV
aQIDAQAB
-----END PUBLIC KEY-----
and a modulus in hexadecimal form:
00:ce:40:49:fd:6b:b2:8f:48:59:59:ae:a8:1f:e8:
43:fb:92:57:d6:b5:7f:4c:07:f7:94:ac:53:3d:fd:
0c:52:b4:44:87:64:b7:40:fc:cb:60:17:54:c4:1c:
88:e7:9d:88:de:70:07:24:08:7a:26:e8:d4:8c:69:
23:e0:ed:72:5f:a3:81:24:72:79:f7:a1:90:9e:fd:
30:05:41:79:b2:bd:10:56:0d:a5:8d:ab:f7:dc:79:
2e:1e:df:a8:b6:b8:98:ee:36:72:f8:e4:e5:8a:f9:
26:75:27:72:85:78:6d:54:d9:70:f8:68:32:43:17:
80:23:87:f5:06:06:84:18:07:dd:f5:02:72:37:dc:
ab:93:26:4b:aa:cf:7e:08:29:8c:a2:0f:19:6d:ca:
aa:4a:54:7f:4b:99:e1:50:99:2e:cd:30:f8:62:f9:
9a:03:8a:24:40:00:f2:3a:d9:2d:4c:2c:94:0b:79:
dd:85:1b:86:a7:8e:75:87:ea:79:58:09:9c:5d:8a:
56:dd:0a:ea:0d:f0:f3:b8:53:32:e5:59:70:20:1f:
c4:03:d7:d9:78:c4:d8:da:d5:a2:ff:b6:27:69:5a:
98:0c:98:e1:42:fd:97:b9:e3:8c:8b:33:02:14:23:
76:6f:2f:9b:95:cf:37:b9:db:8f:5c:94:29:5c:7a:
d5:69
Here is a encrypting function that i want to use for signing a message.
public function encrypt ($m, $e, $n, $s=3) {
$coded = '';
$max = strlen($m);
$packets = ceil($max/$s);
for($i=0; $i<$packets; $i++){
$packet = substr($m, $i*$s, $s);
$code = '0';
for($j=0; $j<$s; $j++){
$code = bcadd($code, bcmul(ord($packet[$j]), bcpow('256',$j)));
}
$code = bcpowmod($code, $e, $n);
$coded .= $code.' ';
}
return trim($coded);
}
Now how could i convert the hexadecimal value into decimal and will it work like this? Please suggest!
I have tested this function by generating publicKey,privateKey,modulus by RSA algorithm and working as charm, but now i need to work with the SSL certificate keys.
Related
Earlier I found out that before using the signature in JWT Library, I need to convert the JSON Web Key (JWK) to PEM format.
Original private key in JWK format:
{
"kty": "EC",
"d": "Rwyv99W3GnfjYbI0X-b5Umhvh88oRCKQkPxiwCPVGgg",
"crv": "P-256",
"x": "sDbcYT8HzBk1tUl849ZHrhpIn8ZV7HfD1DwYdsP1ip0",
"y": "EWodfKWQ6oE0ppyi7tRO_61BgAQsZyDjDGj9kLZiUts"
}
Need to get PEM format, like here:
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEcMr/fVtxp342GyNF/m+VJob4fPKEQikJD8YsAj1RoIoAoGCCqGSM49
AwEHoUQDQgAEsDbcYT8HzBk1tUl849ZHrhpIn8ZV7HfD1DwYdsP1ip0Rah18pZDq
gTSmnKLu1E7/rUGABCxnIOMMaP2QtmJS2w==
-----END EC PRIVATE KEY-----
There is an online converter that does what I need. Is it possible to do the same convertation in Delphi?
You would have everything you need in low-level OpenSSL.
Its API is a little cryptic but you have the EC_POINT*() functions for doing it.
Check what we did in
mormot.crypt.openssl to work with low-level ECC private keys and integrate them with OpenSSL:
ecdsa_sign_osl which takes a raw private key and convert it into OpenSSL PEC_KEY;
OpenSslSaveKeys which saves this key as PEM.
You need to only export the "d": "Rwyv99W3GnfjYbI0X-b5Umhvh88oRCKQkPxiwCPVGgg" parameter. It seems to be the same layout than TEccPrivateKey as used as input parameter in ecdsa_sign_osl().
You may find also some pure pascal code computing ECC prime256v1 in mormot.crypt.ecc256r1.pas.
The solution was found. Read the details here.
Simplified example:
uses
JSON,
EncdDecd;
function Base64urlToBase64(Base64urlStr: String): String;
begin
Result := StringReplace(Base64urlStr,'_','/', [rfReplaceAll]);
Result := StringReplace(Result,'-','+', [rfReplaceAll]);
end;
function JwkToPem(JWK: TJSONObject): String;
var
BinKey: TBytes;
begin
BinKey :=
[$30] + // ASN.1
[$77] + // Length of all following bytes (119 bytes)
[$02] + // Type (integer)
[$01] + // Length of integer (1 byte)
[$01] + // Value of integer (1)
[$04] + // Type (octet string)
[$20] + // Length of string (32 bytes)
DecodeBase64(Base64urlToBase64(JWK.Get('d').JsonValue.Value)) + // Private Key
[$A0] + // Tag 0
[$0A] + // Length of tag (10 bytes)
[$06] + // Type (Object ID)
[$08] + // Length of the Object ID (8 bytes)
[$2A, $86, $48, $CE, $3D, $03, $01, $07] + // - The object ID of the curve prime256v1
[$A1] + // Tag 1
[$44] + // Length of tag (68 bytes)
[$03] + // Type – Bit string
[$42] + // Length of the bit string (66 bytes)
[$00] + // ???
[$04] + // Uncompressed Public Key
DecodeBase64(Base64urlToBase64(JWK.Get('x').JsonValue.Value))+ // Public Key X coord
DecodeBase64(Base64urlToBase64(JWK.Get('y').JsonValue.Value)); // Public Key Y coord
Result :=
'-----BEGIN EC PRIVATE KEY-----'+#13#10+
EncodeBase64(Pointer(BinKey), Length(BinKey))+#13#10+
'-----END EC PRIVATE KEY-----';
end;
I need to upgrade a website I look after to PHP 7.2. In the testing phase i've discovered that one of the plug-in's on the site used the mcrypt library which is no longer available in PHP 7.2.
Essentially this plugin receives PBKDF2 encrypted data from a ticketing system (Tessitura) that returns the user's session key and a time stamp and an encrypted string.
In the control panel I have been given data to use to decrypt this session key such as a Passphrase, Salt, Authentication/HMAC Key , BlockSize, PaddingMode, EncryptionKeyIterations, EncryptionKeyLength and HMACLength
Image of supplied fields
I've been trying to work out how to decrypt the data but I confess i'm struggling. C
an anybody tell me how to use php 7.2 to achieve this? I've found some functions in the openssl suite that look like they may be the correct way to go but they all use different terminology to the information i've been given and I cannot work out where to start, what goes where or what settings to use
Thanks in advance to anybody that can solve this problem!!
As Rob Napier said, PBKDF2 is what the system is using to hash the password being passed into the encryption process. The site is actually using aes-256-cbc encryption. That encryption process can include a password.
After the information is encrypted, that payload is signed with an HMAC key.
You can use the openSSL library to execute all of this in php 7 and higher. Here is some sample code that creates a class to handle the encryption/decryption, for example:
$crypto = new AesCryptoClass('YOUR_PASSPHRASE_HERE',
'YOUR_HMAC_KEY_HERE',
'YOUR_SALT_HERE');
class AesCryptoClass {
// These should not change
private $hmacLength = 32;
private $iterations = 1000;
private $keyLength = 32;
private $blockSize = 16;
private $cipher = 'aes-256-cbc';
function __construct($password,$hmacKey,$salt)
{
$this->password = $password;
$this->hmacKey = $hmacKey;
$this->salt = $salt;
}
function encrypt($plainText)
{
$iv = openssl_random_pseudo_bytes(16);
$encryptedBytes = $this->encryptInner($iv, $plainText);
$encryptedMessage = $iv . $encryptedBytes;
$mac = $this->hashMessage($encryptedMessage);
$secureMessage = $mac . $encryptedMessage;
$encryptedText = base64_encode($secureMessage);
return $encryptedText;
}
function decrypt($encryptedText)
{
$secureMessage = base64_decode($encryptedText);
$mac = substr($secureMessage, 0, $this->hmacLength);
$encryptedMessage = substr($secureMessage, $this->hmacLength);
$newMac = $this->hashMessage($encryptedMessage);
if (strcmp($mac, $newMac) !== 0) {
return "";
}
$iv = substr($encryptedMessage,0, $this->blockSize);
$encryptedBytes = substr($encryptedMessage, $this->blockSize);
$plainText = $this->decryptInner($iv, $encryptedBytes);
return $plainText;
}
function encryptInner($iv, $plainText)
{
$encryptionKey = openssl_pbkdf2($this->password, $this->salt, $this->keyLength, $this->iterations);
return openssl_encrypt($plainText, $this->cipher, $encryptionKey, OPENSSL_RAW_DATA, $iv);
}
function decryptInner($iv, $encryptedBytes)
{
$encryptionKey = openssl_pbkdf2($this->password, $this->salt, $this->keyLength, $this->iterations);
return openssl_decrypt($encryptedBytes, $this->cipher, $encryptionKey, OPENSSL_RAW_DATA, $iv);
}
function hashMessage($encryptedMessage)
{
return pack("H*", hash_hmac("sha256", $encryptedMessage, $this->hmacKey));
}
}
This code and the description of the process are also included here at the bottom of the wiki:
https://bitbucket.org/TN_WebShare/webpro-session-sharing-sample/wiki/Session%20Key%20Encryption%20and%20Decryption
Has anyone already migrate a site from Drupal to Yii?
Is there some code in Yii that can implement the Drupal encryption and salt for user password?
I have, but not to YII. Its not a big deal. You can use the same salt and encryption in YII as well (easier since both are PHP based).
Check these two pages:
http://www.yiiframework.com/wiki/425
https://api.drupal.org/api/drupal/includes!password.inc/function/user_hash_password/7
Thanks Amar, I follow your links and
I create the YII functions for migrating from drupal7.
They work for me and I could save 1 working hour to someone (not more I guess)
I put all of them in
class UserIdentity extends CUserIdentity
and use this way in
..
} else if (self::user_check_password($this->password, $users->password) ) {
..
in public function authenticate()
private function user_check_password($password, $registered_password) {
if (substr($registered_password, 0, 2) == 'U$') {
// This may be an updated password from user_update_7000(). Such hashes
// have 'U' added as the first character and need an extra md5().
$stored_hash = substr($registered_password, 1);
$password = md5($password);
}
else {
$stored_hash = $registered_password;
}
$type = substr($stored_hash, 0, 3);
switch ($type) {
case '$S$':
// A normal Drupal 7 password using sha512.
$hash = self::_password_crypt('sha512', $password, $stored_hash);
break;
case '$H$':
// phpBB3 uses "$H$" for the same thing as "$P$".
case '$P$':
// A phpass password generated using md5. This is an
// imported password or from an earlier Drupal version.
$hash = self::_password_crypt('md5', $password, $stored_hash);
break;
default:
return FALSE;
}
return ($hash && $stored_hash == $hash);
}
private function user_hash_password($password) {
return self::_password_crypt('sha512', $password, self::_password_generate_salt(15));
}
private function _password_crypt($algo, $password, $setting) {
// The first 12 characters of an existing hash are its setting string.
$setting = substr($setting, 0, 12);
if ($setting[0] != '$' || $setting[2] != '$') {
return FALSE;
}
$count_log2 = self::_password_get_count_log2($setting);
// Hashes may be imported from elsewhere, so we allow != DRUPAL_HASH_COUNT
if ($count_log2 < 7 || $count_log2 > 30) {
return FALSE;
}
$salt = substr($setting, 4, 8);
// Hashes must have an 8 character salt.
if (strlen($salt) != 8) {
return FALSE;
}
// Convert the base 2 logarithm into an integer.
$count = 1 << $count_log2;
// We rely on the hash() function being available in PHP 5.2+.
$hash = hash($algo, $salt . $password, TRUE);
do {
$hash = hash($algo, $hash . $password, TRUE);
} while (--$count);
$len = strlen($hash);
$output = $setting . self::_password_base64_encode($hash, $len);
// _password_base64_encode() of a 16 byte MD5 will always be 22 characters.
// _password_base64_encode() of a 64 byte sha512 will always be 86 characters.
$expected = 12 + ceil((8 * $len) / 6);
return (strlen($output) == $expected) ? substr($output, 0, 55) : FALSE;
}
private function _password_generate_salt($count_log2) {
$output = '$S$';
// Ensure that $count_log2 is within set bounds.
$count_log2 = self::_password_enforce_log2_boundaries($count_log2);
// We encode the final log2 iteration count in base 64.
$itoa64 = self::_password_itoa64();
$output .= $itoa64[$count_log2];
// 6 bytes is the standard salt for a portable phpass hash.
$output .= self::_password_base64_encode(self::drupal_random_bytes(6), 6);
return $output;
}
private function _password_enforce_log2_boundaries($count_log2) {
if ($count_log2 < 7) {
return 7;
}
elseif ($count_log2 > 30) {
return 30;
}
return (int) $count_log2;
}
private function _password_itoa64() {
return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
}
private function _password_base64_encode($input, $count) {
$output = '';
$i = 0;
$itoa64 = self::_password_itoa64();
do {
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];
if ($i < $count) {
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count) {
break;
}
if ($i < $count) {
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count) {
break;
}
$output .= $itoa64[($value >> 18) & 0x3f];
} while ($i < $count);
return $output;
}
private function drupal_random_bytes($count) {
// $random_state does not use drupal_static as it stores random bytes.
static $random_state, $bytes, $has_openssl;
$missing_bytes = $count - strlen($bytes);
if ($missing_bytes > 0) {
// PHP versions prior 5.3.4 experienced openssl_random_pseudo_bytes()
// locking on Windows and rendered it unusable.
if (!isset($has_openssl)) {
$has_openssl = version_compare(PHP_VERSION, '5.3.4', '>=') && function_exists('openssl_random_pseudo_bytes');
}
// openssl_random_pseudo_bytes() will find entropy in a system-dependent
// way.
if ($has_openssl) {
$bytes .= openssl_random_pseudo_bytes($missing_bytes);
}
// Else, read directly from /dev/urandom, which is available on many *nix
// systems and is considered cryptographically secure.
elseif ($fh = #fopen('/dev/urandom', 'rb')) {
// PHP only performs buffered reads, so in reality it will always read
// at least 4096 bytes. Thus, it costs nothing extra to read and store
// that much so as to speed any additional invocations.
$bytes .= fread($fh, max(4096, $missing_bytes));
fclose($fh);
}
// If we couldn't get enough entropy, this simple hash-based PRNG will
// generate a good set of pseudo-random bytes on any system.
// Note that it may be important that our $random_state is passed
// through hash() prior to being rolled into $output, that the two hash()
// invocations are different, and that the extra input into the first one -
// the microtime() - is prepended rather than appended. This is to avoid
// directly leaking $random_state via the $output stream, which could
// allow for trivial prediction of further "random" numbers.
if (strlen($bytes) < $count) {
// Initialize on the first call. The contents of $_SERVER includes a mix of
// user-specific and system information that varies a little with each page.
if (!isset($random_state)) {
$random_state = print_r($_SERVER, TRUE);
if (function_exists('getmypid')) {
// Further initialize with the somewhat random PHP process ID.
$random_state .= getmypid();
}
$bytes = '';
}
do {
$random_state = hash('sha256', microtime() . mt_rand() . $random_state);
$bytes .= hash('sha256', mt_rand() . $random_state, TRUE);
} while (strlen($bytes) < $count);
}
}
$output = substr($bytes, 0, $count);
$bytes = substr($bytes, $count);
return $output;
}
private function _password_get_count_log2($setting) {
$itoa64 = self::_password_itoa64();
return strpos($itoa64, $setting[3]);
}
I want to build a message encryption system where users will send message in a encrypted format. I am using GnUPG.I got help from http://www.php.net/manual/en/gnupg.installation.php to install the GnUPG. After install in the server I create the public and private keyring by following code
$GeneratedKey = $gpg->GenKey($name, $comment, $email, $passphrase,$ExpireDate, $KeyType, $KeyLength,$SubkeyType, $SubkeyLength );
function GenKey($RealName, $Comment, $Email, $Passphrase = '', $ExpireDate = 0, $KeyType = 'DSA', $KeyLength = 1024, $SubkeyType = 'ELG-E', $SubkeyLength = 1024)
{
// validates the keytype
if (($KeyType != 'DSA') && ($KeyType != 'RSA')) {
$this->error = 'Invalid Key-Type, the allowed are DSA and RSA';
return false;
}
// validates the subkey
if ((!empty($SubkeyType)) && ($SubkeyType != 'ELG-E')) {
$this->error = 'Invalid Subkey-Type, the allowed is ELG-E';
return false;
}
// validate the expiration date
if (!preg_match('/^(([0-9]+[dwmy]?)|([0-9]{4}-[0-9]{2}-[0-9]{2}))$/', $ExpireDate)) {
$this->error = 'Invalid Expire Date, the allowed values are <iso-date>|(<number>[d|w|m|y])';
return false;
}
// generates the batch configuration script
$batch_script = "Key-Type: $KeyType\n" .
"Key-Length: $KeyLength\n";
if (($KeyType == 'DSA') && ($SubkeyType == 'ELG-E'))
$batch_script .= "Subkey-Type: $SubkeyType\n" .
"Subkey-Length: $SubkeyLength\n";
$batch_script .= "Name-Real: $RealName\n" .
"Name-Comment: $Comment\n" .
"Name-Email: $Email\n" .
"Expire-Date: $ExpireDate\n" .
"Passphrase: $Passphrase\n" .
"%commit\n" .
"%echo done with success\n";
// initialize the output
$contents = '';
// execute the GPG command
if ( $this->_fork_process($this->program_path . ' --homedir ' . $this->home_directory .
' --batch --status-fd 1 --gen-key',
$batch_script, $contents) ) {
$matches = false;
if ( preg_match('/\[GNUPG:\]\sKEY_CREATED\s(\w+)\s(\w+)/', $contents, $matches) )
return $matches[2];
else
return true;
} else
return false;
}
I encrypt by the following code
$gpg = new gnupg();
$gpg->addencryptkey($recipient);
$ciphertext = $gpg->encrypt($plaintext);
Decrypt by the following code
$gpg = new gnupg();
$gpg->adddecryptkey($recipient, $receiver_passphrase);
$plain = $gpg->decrypt($encrypted_text, $plaintext);
BY this I successfully create a folder of a username and generate private and public keyring over there and then send message in a encrypted way and decrypt by the receiver. But my main concern is I don't want to generate user public and private keyring in the server, instead I want to generate public and private keyring in users local computer..
Is it possible to generate public and private key in local computer? Because I don't want user depend on server security. Only receiver will able to decrypt the message.. Not other will able to decrypt..
thanks,
You can create the keys using OpenPGP.js which runs in your client's browser, store the private key somewhere with your client and send nothing but the public one to the server.
// Create new key with RSA encryption (1), 4k length for
// John Doe with password "foobar"
var keys = openpgp.generate_key_pair(1, 4096,
"John Doe john.doe#example.org", "foobar");
keys.privateKeyArmored; // Access private key
keys.publicKeyArmored; // Access public key
I am having issues sending mail with swift mailer when Recipient name contains parentheses ( and )
example code:
$mail = new Swift_Message();
$mail->setTo('recipient#test.com', 'Recipient (bla bla)');
$mail->setFrom('sender#test.com', 'Sender');
$mail->setSubject('Test email');
$mail->setBody('<html><body><h3>Hello</h3></body></html>', 'text/html');
sfContext::getInstance()->getMailer()->send($mail);
If the recipient is using gmail, he does receive the email but when clicking on the down arrow to get more info, The to: part is empty:
The problem is some other email services does not receive that email.
As for the original message content, it's too much details to black out to show here but basically my question is how can I use parentheses without breaking anything.
Seems like base64_encode can help so I modified the swiftmailer class SimpleMessage.php to be sure this fix is applied every time.
Modification of SimpleMessage from this:
public function setTo($addresses, $name = null)
{
if (!is_array($addresses) && isset($name))
{
$addresses = array($addresses => $name);
}
if (!$this->_setHeaderFieldModel('To', (array) $addresses))
{
$this->getHeaders()->addMailboxHeader('To', (array) $addresses);
}
return $this;
}
To this:
public function setTo($addresses, $name = null)
{
// if $name is set, encode it
if(isset($name))
{
$name = $this->encodeName($name);
}
// if $addresses is an non numeric array (email => name), encode each name.
if(is_array($addresses) && array_keys($addresses) !== range(0, count($addresses) - 1))
{
foreach($addresses as $key => $value)
{
$addresses[$key] = $this->encodeName($value);;
}
}
if (!is_array($addresses) && isset($name))
{
$addresses = array($addresses => $name);
}
if (!$this->_setHeaderFieldModel('To', (array) $addresses))
{
$this->getHeaders()->addMailboxHeader('To', (array) $addresses);
}
return $this;
}
/**
* Encode the name to avoid issues with some characters
*
* #param string $name
* #return string
*/
private function encodeName($name)
{
return "=?UTF-8?B?". base64_encode($name) . '?=';
}
This answer helped me: Base64 encode from name for email