diff --git a/src/Exceptions/DecryptException.php b/src/Exceptions/DecryptException.php index f6b7ee6..352848f 100644 --- a/src/Exceptions/DecryptException.php +++ b/src/Exceptions/DecryptException.php @@ -6,7 +6,7 @@ class DecryptException extends \Exception { - public function __construct(string $message = "Cannot decrypt text", int $code = 0, Throwable $previous = null) + public function __construct(string $message = "Cannot decrypt text", int $code = 0, ?Throwable $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/src/RSAParameters.php b/src/RSAParameters.php index c75ef2f..098b5f9 100644 --- a/src/RSAParameters.php +++ b/src/RSAParameters.php @@ -8,10 +8,10 @@ class RSAParameters { private string $privateKey; private string $publicKey; - private string $passphrase; + private ?string $passphrase = 'test_passphrase'; protected array $config = [ - 'digest_alg' => 'sha512', + 'digest_alg' => 'sha256', 'private_key_bits' => 4096, 'private_key_type' => OPENSSL_KEYTYPE_RSA, ]; @@ -31,15 +31,9 @@ public function generateKeys(?string $passphrase = null, ?array $configArgs = nu { $keys = openssl_pkey_new($this->config); - if ($passphrase != null) { - $this->passphrase = $passphrase; - } else { - $this->passphrase = (string)rand(100000, 999999); - } - if ($keys) { - openssl_pkey_export($keys, $private, $passphrase, $configArgs); - $this->privateKey = $private; + openssl_pkey_export($keys, $private); + $this->privateKey = $this->encryptPrivateKey(privateKey: $private); $pub = openssl_pkey_get_details($keys); @@ -51,22 +45,40 @@ public function generateKeys(?string $passphrase = null, ?array $configArgs = nu return $this; } + private function encryptPrivateKey(string $privateKey, string $salt = 'salt'): string + { + $aes = new AESCryptoServiceProvider(); + $aes->generateIV(); + $k = new CryptoKey(); + $key = $k->getCryptographicKey($this->passphrase, $salt); + $aes->setKey($key); + + return $aes->encrypt($privateKey); + } + + private function decryptPrivateKey(string $privateKey, string $salt = 'salt'): string + { + $aes = new AESCryptoServiceProvider(); + $k = new CryptoKey(); + $key = $k->getCryptographicKey($this->passphrase, $salt); + $aes->setKey($key); + + return $aes->decrypt($privateKey); + } + /** * Returns Decrypted Key * * @return string|\OpenSSLAsymmetricKey * @throws DecryptPrivateKeyException */ - public function getPrivateKey(): \OpenSSLAsymmetricKey|string + public function getPrivateKey(string $salt = 'salt', bool $encrypted = false): \OpenSSLAsymmetricKey|string { - if ($this->passphrase != null && $this->privateKey != null) { - $privateKeyResource = openssl_pkey_get_private($this->privateKey, $this->passphrase); - - if ($privateKeyResource == false) { - throw new DecryptPrivateKeyException(); - } - - return $privateKeyResource; + if (!$encrypted) { + return $this->decryptPrivateKey( + privateKey: $this->privateKey, + salt: $salt + ); } return $this->privateKey; @@ -78,7 +90,7 @@ public function getPrivateKey(): \OpenSSLAsymmetricKey|string * @param string $privateKey * @param string $passphrase */ - public function setPrivateKey(string $privateKey, string $passphrase): void + public function setPrivateKey(string $privateKey, string $passphrase, string $salt = 'salt'): void { $this->passphrase = $passphrase; $this->privateKey = $privateKey; @@ -109,7 +121,7 @@ public function setPublicKey(string $publicKey): void * * @return string */ - public function getPassphrase(): string + public function getPassphrase(): ?string { return $this->passphrase; } @@ -142,4 +154,23 @@ public function setConfig(array $config): void { $this->config = $config; } + + /** + * Returns the fingerprint of the public key. + * + * @param bool $md5 Whether to return the MD5 fingerprint instead of SHA-256. + * @return string The fingerprint of the public key. + */ + public function getFingerprint(bool $md5 = false): string + { + $derData = preg_replace('/-----.*?-----/', '', base64_decode($this->publicKey)); + $derData = preg_replace('/\s+/', '', $derData); + $derData = base64_decode($derData); + + if ($md5) { + return implode(':', str_split(hash('md5', $derData), 2)); + } + + return hash('sha256', $derData); + } } diff --git a/src/Tools/RsaParametersWriter.php b/src/Tools/RsaParametersWriter.php index 543f4db..6e4a426 100644 --- a/src/Tools/RsaParametersWriter.php +++ b/src/Tools/RsaParametersWriter.php @@ -31,12 +31,7 @@ public function __construct(RSAParametersLocatorInterface $locator) public function write(RSAParameters $RSAParameters): void { file_put_contents($this->locator->locatePublicKey(), $RSAParameters->getPublicKey()); + file_put_contents($this->locator->locatePrivateKey(), $RSAParameters->getPrivateKey(encrypted: true)); file_put_contents($this->locator->locatePassphrase(), $RSAParameters->getPassphrase()); - - openssl_pkey_export_to_file( - $RSAParameters->getPrivateKey(), - $this->locator->locatePrivateKey(), - $RSAParameters->getPassphrase() - ); } } diff --git a/tests/RSAParametersTest.php b/tests/RSAParametersTest.php index 3ca144a..b4a9866 100644 --- a/tests/RSAParametersTest.php +++ b/tests/RSAParametersTest.php @@ -47,6 +47,7 @@ public function canExportKeysAndImportToFile() : void $reader = new RsaParametersReader($locator); $parameters2 = $reader->read(); + // create new instance of RSA CSP with imported parameters $csp2 = new RSACryptoServiceProvider(); $csp2->setParameters($parameters2); @@ -54,4 +55,4 @@ public function canExportKeysAndImportToFile() : void // Check if imported parameters are same as parameters that was exported $this->assertEquals($text, $csp2->decrypt($encryptedText)); } -} \ No newline at end of file +}