From f19bf7a07ddf01d80863f765ad03ecccf106d4dd Mon Sep 17 00:00:00 2001 From: terrafrost Date: Wed, 6 May 2015 22:55:12 -0500 Subject: [PATCH] RSA: backport getPublicKeyFingerprint from Lukas-W's PR --- phpseclib/Crypt/RSA.php | 36 ++++++++++++++++++++++++++++ tests/Unit/Crypt/RSA/LoadKeyTest.php | 15 ++++++++++++ 2 files changed, 51 insertions(+) diff --git a/phpseclib/Crypt/RSA.php b/phpseclib/Crypt/RSA.php index 53f94354..3c420693 100644 --- a/phpseclib/Crypt/RSA.php +++ b/phpseclib/Crypt/RSA.php @@ -1772,6 +1772,42 @@ class Crypt_RSA return $temp; } + /** + * Returns the public key's fingerprint + * + * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is + * no public key currently loaded, false is returned. + * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716) + * + * @access public + * @param String $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned + * for invalid values. + */ + public function getPublicKeyFingerprint($algorithm = 'md5') + { + if (empty($this->modulus) || empty($this->publicExponent)) { + return false; + } + + $modulus = $this->modulus->toBytes(true); + $publicExponent = $this->publicExponent->toBytes(true); + + $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); + + switch($algorithm) + { + case 'sha256': + $hash = new Crypt_Hash('sha256'); + $base = base64_encode($hash->hash($RSAPublicKey)); + return substr($base, 0, strlen($base) - 1); + case 'md5': + return substr(chunk_split(md5($RSAPublicKey), 2, ':'), 0, -1); + default: + return false; + } + + } + /** * Returns the private key * diff --git a/tests/Unit/Crypt/RSA/LoadKeyTest.php b/tests/Unit/Crypt/RSA/LoadKeyTest.php index 2b9a8f3c..b1603af4 100644 --- a/tests/Unit/Crypt/RSA/LoadKeyTest.php +++ b/tests/Unit/Crypt/RSA/LoadKeyTest.php @@ -241,6 +241,21 @@ ZQIDAQAB $this->assertFalse($rsa->getPrivateKey()); } + + public function testSSHPubKeyFingerprint() + { + $rsa = new Crypt_RSA(); + $key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD9K+ebJRMN10kGanhi6kDz6EYFqZttZWZh0'. + 'YoEbIbbere9N2Yvfc7oIoCTHYowhXND9WSJaIs1E4bx0085CZnofWaqf4NbZTzAh18iZup08ec'. + 'COB5gJVS1efpgVSviDF2L7jxMsBVoOBfqsmA8m0RwDDVezyWvw4y+STSuVzu2jI8EfwN7ZFGC6'. + 'Yo8m/Z94qIGzqPYGKJLuCeidB0TnUE0ZtzOJTiOc/WoTm/NOpCdfQZEJggd1MOTi+QUnqRu4Wu'. + 'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'. + 'mWG5tUlUI/5'; + $this->assertTrue($rsa->loadKey($key)); + $this->assertSame($rsa->getPublicKeyFingerprint('md5'), 'bd:2c:2f:31:b9:ef:b8:f8:ad:fc:40:a6:94:4f:28:82'); + $this->assertSame($rsa->getPublicKeyFingerprint('sha256'), 'N9sV2uSNZEe8TITODku0pRI27l+Zk0IY0TrRTw3ozwM'); + } + public function testSetPrivate() { $rsa = new Crypt_RSA();