On Mon, 4 Aug 2025 19:59:50 GMT, Sebastian Stenzel <d...@openjdk.org> wrote:
>> `getEncoded` is the whole PKCS #8 encoding. >> `getRawBytes` returns the content of the `privateKey` field inside the PKCS >> #8 encoding. >> `getExpanded` is not related to encoding. It's what the underlying >> `NamedKEM` or `NamedSignature` will use. >> >> For ML-KEM, `getRawBytes` might be any of the 3 CHOICEs: seed, expandedKey, >> or both. `getExpanded` is always the expanded format (defined in FIPS 203). >> There is a slight difference even if `getRawBytes` is using the expandedKey >> choice: it has the OCTET STRING header but `getExpanded` does not. >> >> `engineTranslateKey` can re-encode the key depending on the >> "jdk.mlkem.pkcs8.encoding" security property. Therefore it works on the >> `getRawBytes` level. > > In X-Wing, the expanded decapsulation key is referred to as `sk_m`. I.e. > *without* the CHOICE structure. So in order to have > `NamedPKCS8Key.privKeyMaterial` contain the choice, I would have to do this: > > > byte[] keyBytesWrappedInChoice = > KeyChoices.writeToChoice(KeyChoices.Type.EXPANDED_KEY, null, sk_m); > PrivateKey key = NamedPKCS8Key.internalCreate("ML-KEM", "ML-KEM-768", > keyBytesWrappedInChoice, null); > > > However, if I now call `keyFactory.translateKey(key)`, it'll throw: > > > java.security.InvalidKeyException: key contains not enough info to translate > at > java.base/sun.security.util.KeyChoices.choiceToChoice(KeyChoices.java:220) > at > java.base/com.sun.crypto.provider.ML_KEM_Impls$KF.engineTranslateKey(ML_KEM_Impls.java:133) > at java.base/java.security.KeyFactory.translateKey(KeyFactory.java:475) > > > in base64 `sk_m` has this value (test case 1 from [X-Wing test > vectors](https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-08#appendix-C)): > > > IDjHPToyMBF3joBR7joyxgHNZdrAqPmpQIEj8GRIi+thihFD1Fqc+BbMlZuDnLsPH5y7DJWqXHsqhQNeiMRkT1VZjVF7psO12woyNCIYSHFQe8O/BspLfeOW/MFH4tONheMqoIKMUHvC28nEk4Q57YciB7y//iNoevxrdhG4/XrCetNairsm2RB0AQtsc1WhUUyluoExawtc3bmm2BmiGocA2PmbB4hBPVw8fXyhm4ACCJqKjKJ7BZBelLxh49fPLbaXxZYrC0s5O7Cbv/oujGxuk8K8NOpIFxZVSdota6ikQDe4ELd8Dhk0ppU3FjE0JhsjQshoNGtB2AkDgcDADDMb44giv+KWv8o1khgg52Q76KgrzlnMZdUn+ujHA1lK2FcYT+R52uyrJJec8WKCVtSPJdp+ajBrOaCoUlQMrRgMUMC0xnegLoubeWQBxdwUpSgloIjDG0RxVQRPCwgYczWfClLEaOaK/TlOiUisecKTeECk38gfr1IUvdocAtTO62klYLa4Z9fKO/uvXxwzHjap6uaWsJJeZ/GUMrCX+Helmdiu3DArkTgQl9kNIYgkapcOw1gKqxVDCtdHcntCp/fDy3sSDKaM1mZHdtmdZfMIbKW8sZiPHbyZqsJtZwEL0wjAzpeVnouGSCEvPSYuTfW3ThDLsKs+oFxI32S4EvgQNUd2vFd2kuUhmct6YDTLA9hh+Vs7jlEUYjtx1fAUIiO6F9tR1KWRskqkY8qWrWpJYBg61ySdKUq/kHEvhcieVqMGcId8DFpIUDhsCoIjmAQrabZyvTWb9ndKaboaa5kOFNGrEoA1iHovnOZgxhSQf/IXWncIZOJ0B+MSIYJ/OBgU2OrGvmq/28pxtHK1iSnBN5c2JXK/qhZdhkqdzHFhDbOyM7QOOyVnJuMXO3x+fXXPlCgrpVYivOZ5lhfJEuUQMPgm0abCeHScyGRSw2KXkXpg7icb/gWsTSedtEpGcTMie4BqeZaUZRYl xQoGeRCeQPZvXIS7ajlPmBxge1S5DDCCw4Q9gUgCAXo6DNQ10ABGXTmba6kkUwFz+xREY1sapcykudONJ7eo8NUkerE0I/pGUErLZrBulhERusBpPuB9FIKXNdY6hEei9OxgfwKWfGMeUrtoUDOrv9hvViBycHXNP0UroNeTU2au3ycSwtkquVNHYtG94DOi8/Bu59ueXwEx4TZNrXNyW9NwknYF7TgZQBm55PVHurYtq1Cy4Wq2r5TLbFUe5DearAdyKZy746WLCOm29wyp7HRvIsSpTqlyYAla5PymyQov0lqbJexd9bAnXUhOByJqHXM0oou+JIpcVrJSQMuE39soR6iFHhB9icVUxjOKjlWr1zeu30EEzAhVD3JKk9gNrImWY+UJkXuWvfFcowE/EmIDDckeqHqrx8iVDsF0g0pLNYgTI6okoHMLccBHolui9abEBPcswpSRDuDOkDUbuESkSAqiXGRS9NClUTkKLToMyByJshhOHEhONaNrxlAxd4psk+aNscF84sAfABBjd/R84gU... If you manually create an expanded-only key and then try to call`translateKey` on it but the security property is using the default value "seed", then of course the translation will not work. Anyway, I don't think X-Wing implementation needs to touch that property. The X-Wing private key is always the 32-byte seed, and its "expanded" form can include the whole `expandDecapsulationKey` output, and then you can simply call internal `ML-KEM` methods on it. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/24969#discussion_r2252579592