Path: blob/master/src/jdk.crypto.ec/share/classes/sun/security/ec/ed/EdDSAParameters.java
41162 views
/*1* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.security.ec.ed;2526import sun.security.ec.ParametersMap;27import sun.security.provider.SHAKE256;28import sun.security.util.ObjectIdentifier;29import sun.security.util.KnownOIDs;30import sun.security.util.math.*;31import sun.security.util.math.intpoly.*;32import sun.security.x509.AlgorithmId;3334import java.io.IOException;35import java.math.BigInteger;36import java.nio.charset.StandardCharsets;37import java.security.*;38import java.security.spec.*;39import java.util.function.Function;4041/*42* The set of parameters that defines an instance of the EdDSA signature43* scheme.44*/45public class EdDSAParameters {4647public interface DigesterFactory {48// Default digest creator49Digester createDigester();5051// Override this method if multiple key lengths are needed52default Digester createDigester(int len) {53return createDigester();54}5556// Return a digest over all the provided byte arrays57default byte[] digest(byte[]... data) {58Digester d = createDigester();59for (byte[] curData : data) {60d.update(curData, 0, curData.length);61}62return d.digest();63}64}6566// Hash for Ed2551967private static class SHA512DigesterFactory implements DigesterFactory {68@Override69public Digester createDigester() {70try {71MessageDigest md = MessageDigest.getInstance("SHA-512");72return new MessageDigester(md);73} catch (NoSuchAlgorithmException ex) {74throw new ProviderException(ex);75}76}77}7879// Hash for Ed44880private static class SHAKE256DigesterFactory implements DigesterFactory {81@Override82// Most usage for Ed448 is 114bytes long83public Digester createDigester() {84return new SHAKE256Digester(114);85}8687// Ed448 uses 64bytes long hasg for the signature message88@Override89public Digester createDigester(int len) {90return new SHAKE256Digester(len);91}92}9394public interface Digester {95void update(byte data);96void update(byte[] data, int off, int len);97byte[] digest();98}99100private static class MessageDigester implements Digester {101private final MessageDigest md;102103private MessageDigester(MessageDigest md) {104this.md = md;105}106107@Override108public void update(byte data) {109md.update(data);110}111@Override112public void update(byte[] data, int off, int len) {113md.update(data, off, len);114}115@Override116public byte[] digest() {117try {118return md.digest();119} finally {120md.reset();121}122}123}124125private static class SHAKE256Digester implements Digester {126SHAKE256 md;127128SHAKE256Digester(int len) {129md = new SHAKE256(len);130}131@Override132public void update(byte data) {133md.update(data);134}135@Override136public void update(byte[] data, int off, int len) {137md.update(data, off, len);138}139@Override140public byte[] digest() {141try {142return md.digest();143} finally {144md.reset();145}146}147}148149static ParametersMap<EdDSAParameters> namedParams = new ParametersMap<>();150151private final String name;152private final ObjectIdentifier oid;153private final IntegerFieldModuloP field;154private final IntegerFieldModuloP orderField;155private final ImmutableIntegerModuloP d;156private final EdECOperations edOperations;157private final DigesterFactory digester;158private final int keyLength;159private final int bits;160private final int logCofactor;161private final Function<EdDSAParameterSpec, byte[]> dom;162163public EdDSAParameters(String name, ObjectIdentifier oid,164IntegerFieldModuloP field,165IntegerFieldModuloP orderField,166ImmutableIntegerModuloP d,167EdECOperations edOps,168DigesterFactory digester,169Function<EdDSAParameterSpec, byte[]> dom,170int keyLength, int bits, int logCofactor) {171this.oid = oid;172this.name = name;173this.field = field;174this.orderField = orderField;175this.d = d;176this.edOperations = edOps;177this.digester = digester;178this.keyLength = keyLength;179this.bits = bits;180this.logCofactor = logCofactor;181this.dom = dom;182}183184public String getName() {185return name;186}187public ObjectIdentifier getOid() {188return oid;189}190public IntegerFieldModuloP getField() {191return field;192}193public IntegerFieldModuloP getOrderField() {194return orderField;195}196public ImmutableIntegerModuloP getD() {197return d;198}199public EdECOperations getEdOperations() {200return edOperations;201}202public int getKeyLength() {203return keyLength;204}205public int getBits() {206return bits;207}208public int getLogCofactor() {209return logCofactor;210}211212public Digester createDigester() {213return digester.createDigester();214}215216public Digester createDigester(int len) {217return digester.createDigester(len);218}219220public byte[] digest(byte[]... data) {221return digester.digest(data);222}223224public byte[] dom(EdDSAParameterSpec sigParams) {225return dom.apply(sigParams);226}227228private static final String prefixStr25519 =229"SigEd25519 no Ed25519 collisions";230private static final String prefixStr448 = "SigEd448";231232// Used for Ed25519233static byte[] dom2(EdDSAParameterSpec sigParams) {234if (!sigParams.isPrehash() && !sigParams.getContext().isPresent()) {235return new byte[0];236}237return domImpl(prefixStr25519, sigParams);238}239240// Used for Ed488241static byte[] dom4(EdDSAParameterSpec sigParams) {242return domImpl(prefixStr448, sigParams);243}244245static byte[] domImpl(String prefixStr, EdDSAParameterSpec sigParams) {246byte[] prefix = prefixStr.getBytes(StandardCharsets.US_ASCII);247byte[] context = sigParams.getContext().orElse(new byte[0]);248int length = prefix.length + 2 + context.length;249byte[] result = new byte[length];250System.arraycopy(prefix, 0, result, 0, prefix.length);251byte x = (byte) (sigParams.isPrehash() ? 1 : 0);252result[prefix.length] = x;253result[prefix.length + 1] = (byte) context.length;254System.arraycopy(context, 0, result, prefix.length + 2,255context.length);256return result;257}258259static {260// set up Ed25519261IntegerFieldModuloP ed25519Field = new IntegerPolynomial25519();262IntegerFieldModuloP ed25519OrderField = new Curve25519OrderField();263BigInteger biD = new BigInteger("3709570593466943934313808350875" +264"4565189542113879843219016388785533085940283555");265ImmutableIntegerModuloP d = ed25519Field.getElement(biD);266BigInteger baseX = new BigInteger("15112221349535400772501151409" +267"588531511454012693041857206046113283949847762202");268BigInteger baseY = new BigInteger("46316835694926478169428394003" +269"475163141307993866256225615783033603165251855960");270EdECOperations edOps = new Ed25519Operations(d, baseX, baseY);271String name = NamedParameterSpec.ED25519.getName();272ObjectIdentifier oid = ObjectIdentifier.of(KnownOIDs.Ed25519);273int bits = 255;274DigesterFactory digester = new SHA512DigesterFactory();275EdDSAParameters params = new EdDSAParameters(name, oid,276ed25519Field, ed25519OrderField, d, edOps,277digester, EdDSAParameters::dom2, 32, bits, 3);278279namedParams.put(name, oid, bits, params);280281// set up Ed448282IntegerFieldModuloP ed448Field = new IntegerPolynomial448();283IntegerFieldModuloP ed448OrderField = new Curve448OrderField();284biD = ed448Field.getSize().subtract(new BigInteger("39081"));285d = ed448Field.getElement(biD);286baseX = new BigInteger("224580040295924300187604334" +287"099896036246789641632564134246125461686950415467406032909" +288"029192869357953282578032075146446173674602635247710");289baseY = new BigInteger("298819210078481492676017930" +290"443930673437544040154080242095928241372331506189835876003" +291"536878655418784733982303233503462500531545062832660");292edOps = new Ed448Operations(d, baseX, baseY);293name = NamedParameterSpec.ED448.getName();294oid = ObjectIdentifier.of(KnownOIDs.Ed448);295bits = 448;296digester = new SHAKE256DigesterFactory();297params = new EdDSAParameters(name, oid,298ed448Field, ed448OrderField, d, edOps,299digester, EdDSAParameters::dom4, 57, bits, 2);300301namedParams.put(name, oid, bits, params);302303namedParams.fix();304}305306public static307<T extends Throwable>308EdDSAParameters getBySize(Function<String, T> exception,309int size) throws T {310311return namedParams.getBySize(exception, size);312}313314public static315<T extends Throwable>316EdDSAParameters get(Function<String, T> exception,317AlgorithmId algId) throws T {318319return namedParams.get(exception, algId);320}321322public static323<T extends Throwable>324EdDSAParameters get(Function<String, T> exception,325AlgorithmParameterSpec params) throws T {326327return namedParams.get(exception, params);328}329}330331332