Skip to content

Commit

Permalink
Add PKCS#8 parsing code
Browse files Browse the repository at this point in the history
  • Loading branch information
kelvinmo committed Sep 20, 2024
1 parent 4101f21 commit e2fdc61
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
28 changes: 28 additions & 0 deletions src/SimpleJWT/Keys/RSAKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,34 @@ public function __construct($data, string $format, ?string $password = null, ?st
$jwk['dp'] = Util::base64url_encode($seq->getChildAt(6)->getValueAsUIntOctets());
$jwk['dq'] = Util::base64url_encode($seq->getChildAt(7)->getValueAsUIntOctets());
$jwk['qi'] = Util::base64url_encode($seq->getChildAt(8)->getValueAsUIntOctets());
} elseif (preg_match(Key::PEM_PKCS8_PRIVATE, $data, $matches)) {
/** @var string $binary */
$binary = base64_decode($matches[1]);
if ($binary == FALSE) throw new KeyException('Cannot read PEM key');

$seq = $der->decode($binary);

$version = $seq->getChildAt(0)->getValue();
if ($version != 0) throw new KeyException('Invalid private key version: ' . $version);

$key_oid = $seq->getChildAt(1)->getChildAt(0)->getValue();
if ($key_oid != self::OID) throw new KeyException('Invalid key type: ' . $key_oid);

$private_octet_string = $seq->getChildAt(2)->getValue();
$private_seq = $der->decode($private_octet_string);

$version = $private_seq->getChildAt(0)->getValue();
if ($version != 0) throw new KeyException('Unsupported RSA private key version');

$jwk['kty'] = self::KTY;
$jwk['n'] = Util::base64url_encode($private_seq->getChildAt(1)->getValueAsUIntOctets());
$jwk['e'] = Util::base64url_encode($private_seq->getChildAt(2)->getValueAsUIntOctets());
$jwk['d'] = Util::base64url_encode($private_seq->getChildAt(3)->getValueAsUIntOctets());
$jwk['p'] = Util::base64url_encode($private_seq->getChildAt(4)->getValueAsUIntOctets());
$jwk['q'] = Util::base64url_encode($private_seq->getChildAt(5)->getValueAsUIntOctets());
$jwk['dp'] = Util::base64url_encode($private_seq->getChildAt(6)->getValueAsUIntOctets());
$jwk['dq'] = Util::base64url_encode($private_seq->getChildAt(7)->getValueAsUIntOctets());
$jwk['qi'] = Util::base64url_encode($private_seq->getChildAt(8)->getValueAsUIntOctets());
} else {
throw new KeyException('Unrecognised key format');
}
Expand Down
13 changes: 12 additions & 1 deletion tests/KeyFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,25 @@ public function testPEMRSA_PKCS1() {
$this->assertEquals("2sUA6n24v51XMCk_H3WKTELYfEyWzdr6yI3a8xNol8RlLNcjr9NxthPWkOGY6uT1JAbDgBNsiPQXpAiOdRD5FQ", $key_data['p']);
$this->assertEquals("xFpV_GjvAlkzeElY_fb5AWgV9_APIfyuo3NxqmvaRTIUyatsHdrUNE0jsOTJF-2uZZ818sbHltDOb-x3_3y0lw", $key_data['q']);

$pem = file_get_contents('rsa_public_pkcs1.pem');
$pem = file_get_contents('rsa_public.pem');
$key = KeyFactory::create($pem, 'pem');
$this->assertInstanceOf(RSAKey::class, $key);
$key_data = $key->getKeyData();
$this->assertTrue($key->isPublic());
$this->assertEquals("p8wHcPeYsIbQBwFg-mUXIFjZI-b1gQJuNoGboa3ub7KMVjmob9c4mOqc8j2u9cMS6PLnqGMIiM2H1HVDZSwZs6kS7Kq942uNBsut2cHy-PZd5Jq3cWIoQZwnhrjg_OfwbJugYeGe0Orub8J42qyT8HuhLX65Q6iSSf_3bo1Rr2M", $key_data['n']);
}

public function testPEMRSA_PKCS8() {
$pem = file_get_contents('rsa_private_pkcs8.pem');
$key = KeyFactory::create($pem, 'pem');
$this->assertInstanceOf(RSAKey::class, $key);
$key_data = $key->getKeyData();
$this->assertFalse($key->isPublic());
$this->assertEquals("p8wHcPeYsIbQBwFg-mUXIFjZI-b1gQJuNoGboa3ub7KMVjmob9c4mOqc8j2u9cMS6PLnqGMIiM2H1HVDZSwZs6kS7Kq942uNBsut2cHy-PZd5Jq3cWIoQZwnhrjg_OfwbJugYeGe0Orub8J42qyT8HuhLX65Q6iSSf_3bo1Rr2M", $key_data['n']);
$this->assertEquals("Wxts7umA_lg0m5kkDtDUvbuAKv48TtADB5VX63GFBSDtEeQ8kH1LPbwle2ICnW5N1i4NmmArQhxWpAUHkudfDExa9fZf5wUtsDlw8zNhzoDKqtw50D1BhWCfYO19IobTL-x3RJmPAepK5IH8ZYfGbQD2ZEwN0WF2I8sBg4Pu6Q", $key_data['d']);
$this->assertEquals("2sUA6n24v51XMCk_H3WKTELYfEyWzdr6yI3a8xNol8RlLNcjr9NxthPWkOGY6uT1JAbDgBNsiPQXpAiOdRD5FQ", $key_data['p']);
$this->assertEquals("xFpV_GjvAlkzeElY_fb5AWgV9_APIfyuo3NxqmvaRTIUyatsHdrUNE0jsOTJF-2uZZ818sbHltDOb-x3_3y0lw", $key_data['q']);
}

public function testPEMEC() {
$pem = file_get_contents('ec_private.pem');
Expand Down
16 changes: 16 additions & 0 deletions tests/rsa_private_pkcs8.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN PRIVATE KEY-----
MIICdAIBADANBgkqhkiG9w0BAQEFAASCAl4wggJaAgEAAoGBAKfMB3D3mLCG0AcB
YPplFyBY2SPm9YECbjaBm6Gt7m+yjFY5qG/XOJjqnPI9rvXDEujy56hjCIjNh9R1
Q2UsGbOpEuyqveNrjQbLrdnB8vj2XeSat3FiKEGcJ4a44Pzn8GyboGHhntDq7m/C
eNqsk/B7oS1+uUOokkn/926NUa9jAgMBAAECf1sbbO7pgP5YNJuZJA7Q1L27gCr+
PE7QAweVV+txhQUg7RHkPJB9Sz28JXtiAp1uTdYuDZpgK0IcVqQFB5LnXwxMWvX2
X+cFLbA5cPMzYc6AyqrcOdA9QYVgn2DtfSKG0y/sd0SZjwHqSuSB/GWHxm0A9mRM
DdFhdiPLAYOD7ukCQQDaxQDqfbi/nVcwKT8fdYpMQth8TJbN2vrIjdrzE2iXxGUs
1yOv03G2E9aQ4Zjq5PUkBsOAE2yI9BekCI51EPkVAkEAxFpV/GjvAlkzeElY/fb5
AWgV9/APIfyuo3NxqmvaRTIUyatsHdrUNE0jsOTJF+2uZZ818sbHltDOb+x3/3y0
lwJAJKcE9ESEA3Z0+Riv/rFOrmA0rP6X9X1OrvM1T6xcxbCd0tlonTirwHmqZTOm
zxP1Dkgj0P1wHbHnlA/q7iod0QJBAKcmd7ht47lOEkC9v+JCkmseHkV4uIkoP8qp
BgQb2C27mnKrWVh45ti3KkD2IjIahbHAvP41Nccvbe1dkjGOCXUCQGbnRafT+O5B
YNjKRUNVDDyTlrdrAfG/C3v6REH3Q+6Z7kCYBi1ZyryUUwH+2iLpO9+6w1geGFPT
siByv/VbT1I=
-----END PRIVATE KEY-----
File renamed without changes.

0 comments on commit e2fdc61

Please sign in to comment.