View Javadoc
1   /*
2    * Copyright (c) 2002-2026 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.crypto;
16  
17  import java.util.Map;
18  import java.util.Set;
19  
20  import org.htmlunit.corejs.javascript.Scriptable;
21  import org.htmlunit.corejs.javascript.ScriptableObject;
22  import org.htmlunit.corejs.javascript.VarScope;
23  import org.htmlunit.javascript.JavaScriptEngine;
24  
25  /**
26   * Internal helper representing EC key algorithm parameters.
27   * Used by {@link SubtleCrypto} for ECDSA and ECDH key operations.
28   *
29   * @author Lai Quang Duong
30   * @author Ronald Brill
31   */
32  final class EcKeyAlgorithm implements KeyAlgorithm {
33  
34      static final Set<String> SUPPORTED_NAMES = Set.of("ECDSA", "ECDH");
35  
36      private static final Map<String, String> CURVE_TO_JCA = Map.of(
37              "P-256", "secp256r1",
38              "P-384", "secp384r1",
39              "P-521", "secp521r1"
40      );
41  
42      private final String name_;
43      private final String namedCurve_;
44  
45      EcKeyAlgorithm(final String name, final String namedCurve) {
46          if (!SUPPORTED_NAMES.contains(name)) {
47              throw new UnsupportedOperationException("EC " + name);
48          }
49          name_ = name;
50  
51          if (!CURVE_TO_JCA.containsKey(namedCurve)) {
52              throw new UnsupportedOperationException("EC curve " + namedCurve);
53          }
54          namedCurve_ = namedCurve;
55      }
56  
57      /**
58       * Parses EC key algorithm parameters from a JS object.
59       *
60       * @param keyGenParams the JS algorithm parameters object
61       * @return the parsed EcKeyAlgorithm
62       */
63      static EcKeyAlgorithm from(final Scriptable keyGenParams) {
64          final String name = SubtleCrypto.resolveAlgorithmName(keyGenParams);
65  
66          final String namedCurve = JavaScriptEngine.toString(SubtleCrypto.getRequiredMember(keyGenParams, "namedCurve"));
67          return new EcKeyAlgorithm(name, namedCurve);
68      }
69  
70      static boolean isSupported(final String name) {
71          return SUPPORTED_NAMES.contains(name);
72      }
73  
74      @Override
75      public String getName() {
76          return name_;
77      }
78  
79      String getNamedCurve() {
80          return namedCurve_;
81      }
82  
83      /**
84       * Returns the JCA curve name (e.g. "secp256r1" for "P-256").
85       *
86       * @return the JCA curve name (e.g. "secp256r1" for "P-256")
87       */
88      String getJavaCurveName() {
89          return CURVE_TO_JCA.get(namedCurve_);
90      }
91  
92      /**
93       * Converts to a JS object matching the {@code EcKeyAlgorithm} dictionary:
94       * {@code {name: "ECDSA", namedCurve: "P-256"}}.
95       *
96       * @param scope the JS scope for prototype/parent setup
97       * @return the JS algorithm object
98       */
99      @Override
100     public Scriptable toScriptableObject(final VarScope scope) {
101         final Scriptable algorithm = JavaScriptEngine.newObject(scope);
102         ScriptableObject.putProperty(algorithm, "name", getName());
103         ScriptableObject.putProperty(algorithm, "namedCurve", getNamedCurve());
104         return algorithm;
105     }
106 }