|
13 | 13 | */
|
14 | 14 | class JwkFactory
|
15 | 15 | {
|
| 16 | + private const EC_CURVE_MAP = [ |
| 17 | + '1.2.840.10045.3.1.7' => ['name' => 'P-256', 'bits' => 256], |
| 18 | + '1.3.132.0.34' => ['name' => 'P-384', 'bits' => 384], |
| 19 | + '1.3.132.0.35' => ['name' => 'P-521', 'bits' => 512] |
| 20 | + ]; |
| 21 | + |
16 | 22 | /**
|
17 | 23 | * Create JWK for signatures generated with HMAC and SHA256
|
18 | 24 | *
|
@@ -115,6 +121,75 @@ public function createVerifyRs512(string $publicKey): Jwk
|
115 | 121 | return $this->createVerifyRsa(512, $publicKey);
|
116 | 122 | }
|
117 | 123 |
|
| 124 | + /** |
| 125 | + * Create JWK to sign JWS with ECDSA using P-256 and SHA-256. |
| 126 | + * |
| 127 | + * @param string $privateKey |
| 128 | + * @param string|null $passPhrase |
| 129 | + * @return Jwk |
| 130 | + */ |
| 131 | + public function createSignEs256(string $privateKey, ?string $passPhrase): Jwk |
| 132 | + { |
| 133 | + return $this->createSignEs(256, $privateKey, $passPhrase); |
| 134 | + } |
| 135 | + |
| 136 | + /** |
| 137 | + * Create JWK to verify JWS signed with ECDSA using P-256 and SHA-256. |
| 138 | + * |
| 139 | + * @param string $publicKey |
| 140 | + * @return Jwk |
| 141 | + */ |
| 142 | + public function createVerifyEs256(string $publicKey): Jwk |
| 143 | + { |
| 144 | + return $this->createVerifyEs(256, $publicKey); |
| 145 | + } |
| 146 | + |
| 147 | + /** |
| 148 | + * Create JWK to sign JWS with ECDSA using P-384 and SHA-384 . |
| 149 | + * |
| 150 | + * @param string $privateKey |
| 151 | + * @param string|null $passPhrase |
| 152 | + * @return Jwk |
| 153 | + */ |
| 154 | + public function createSignEs384(string $privateKey, ?string $passPhrase): Jwk |
| 155 | + { |
| 156 | + return $this->createSignEs(384, $privateKey, $passPhrase); |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Create JWK to verify JWS signed with ECDSA using P-384 and SHA-384 . |
| 161 | + * |
| 162 | + * @param string $publicKey |
| 163 | + * @return Jwk |
| 164 | + */ |
| 165 | + public function createVerifyEs384(string $publicKey): Jwk |
| 166 | + { |
| 167 | + return $this->createVerifyEs(384, $publicKey); |
| 168 | + } |
| 169 | + |
| 170 | + /** |
| 171 | + * Create JWK to sign JWS with ECDSA using P-521 and SHA-512. |
| 172 | + * |
| 173 | + * @param string $privateKey |
| 174 | + * @param string|null $passPhrase |
| 175 | + * @return Jwk |
| 176 | + */ |
| 177 | + public function createSignEs512(string $privateKey, ?string $passPhrase): Jwk |
| 178 | + { |
| 179 | + return $this->createSignEs(512, $privateKey, $passPhrase); |
| 180 | + } |
| 181 | + |
| 182 | + /** |
| 183 | + * Create JWK to verify JWS signed with ECDSA using P-521 and SHA-512. |
| 184 | + * |
| 185 | + * @param string $publicKey |
| 186 | + * @return Jwk |
| 187 | + */ |
| 188 | + public function createVerifyEs512(string $publicKey): Jwk |
| 189 | + { |
| 190 | + return $this->createVerifyEs(512, $publicKey); |
| 191 | + } |
| 192 | + |
118 | 193 | private function createHmac(int $bits, string $key): Jwk
|
119 | 194 | {
|
120 | 195 | if (strlen($key) < 128) {
|
@@ -186,6 +261,57 @@ private function createVerifyRsa(int $bits, string $key): Jwk
|
186 | 261 | );
|
187 | 262 | }
|
188 | 263 |
|
| 264 | + private function createSignEs(int $bits, string $key, ?string $pass): Jwk |
| 265 | + { |
| 266 | + $resource = openssl_get_privatekey($key, (string)$pass); |
| 267 | + $keyData = openssl_pkey_get_details($resource)['ec']; |
| 268 | + openssl_free_key($resource); |
| 269 | + if (!array_key_exists($keyData['curve_oid'], self::EC_CURVE_MAP)) { |
| 270 | + throw new \RuntimeException('Unsupported EC curve'); |
| 271 | + } |
| 272 | + if ($bits !== self::EC_CURVE_MAP[$keyData['curve_oid']]['bits']) { |
| 273 | + throw new \RuntimeException('The key cannot be used with SHA-' .$bits .' hashing algorithm'); |
| 274 | + } |
| 275 | + |
| 276 | + return new Jwk( |
| 277 | + Jwk::KEY_TYPE_EC, |
| 278 | + [ |
| 279 | + 'd' => self::base64Encode($keyData['d']), |
| 280 | + 'x' => self::base64Encode($keyData['x']), |
| 281 | + 'y' => self::base64Encode($keyData['y']), |
| 282 | + 'crv' => self::EC_CURVE_MAP[$keyData['curve_oid']]['name'] |
| 283 | + ], |
| 284 | + Jwk::PUBLIC_KEY_USE_SIGNATURE, |
| 285 | + null, |
| 286 | + 'ES' .$bits |
| 287 | + ); |
| 288 | + } |
| 289 | + |
| 290 | + private function createVerifyEs(int $bits, string $key): Jwk |
| 291 | + { |
| 292 | + $resource = openssl_get_publickey($key); |
| 293 | + $keyData = openssl_pkey_get_details($resource)['ec']; |
| 294 | + openssl_free_key($resource); |
| 295 | + if (!array_key_exists($keyData['curve_oid'], self::EC_CURVE_MAP)) { |
| 296 | + throw new \RuntimeException('Unsupported EC curve'); |
| 297 | + } |
| 298 | + if ($bits !== self::EC_CURVE_MAP[$keyData['curve_oid']]['bits']) { |
| 299 | + throw new \RuntimeException('The key cannot be used with SHA-' .$bits .' hashing algorithm'); |
| 300 | + } |
| 301 | + |
| 302 | + return new Jwk( |
| 303 | + Jwk::KEY_TYPE_EC, |
| 304 | + [ |
| 305 | + 'x' => self::base64Encode($keyData['x']), |
| 306 | + 'y' => self::base64Encode($keyData['y']), |
| 307 | + 'crv' => self::EC_CURVE_MAP[$keyData['curve_oid']]['name'] |
| 308 | + ], |
| 309 | + Jwk::PUBLIC_KEY_USE_SIGNATURE, |
| 310 | + null, |
| 311 | + 'ES' .$bits |
| 312 | + ); |
| 313 | + } |
| 314 | + |
189 | 315 | /**
|
190 | 316 | * Encode value into Base64Url format.
|
191 | 317 | *
|
|
0 commit comments