package net.i2p.crypto.eddsa; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.KeyPairGeneratorSpi; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.util.Hashtable; import net.i2p.crypto.eddsa.spec.EdDSAGenParameterSpec; import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec; import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; import net.i2p.util.RandomSource; /** * Default strength is 256 * * @since 0.9.15 */ public final class KeyPairGenerator extends KeyPairGeneratorSpi { private static final int DEFAULT_STRENGTH = 256; private EdDSAParameterSpec edParams; private SecureRandom random; private boolean initialized; private static final Hashtable<Integer, AlgorithmParameterSpec> edParameters; static { edParameters = new Hashtable<Integer, AlgorithmParameterSpec>(); edParameters.put(Integer.valueOf(DEFAULT_STRENGTH), new EdDSAGenParameterSpec(EdDSANamedCurveTable.CURVE_ED25519_SHA512)); } public void initialize(int strength, SecureRandom random) { AlgorithmParameterSpec edParams = edParameters.get(Integer.valueOf(strength)); if (edParams == null) throw new InvalidParameterException("unknown key type."); try { initialize(edParams, random); } catch (InvalidAlgorithmParameterException e) { throw new InvalidParameterException("key type not configurable."); } } @Override public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if (params instanceof EdDSAParameterSpec) { edParams = (EdDSAParameterSpec) params; } else if (params instanceof EdDSAGenParameterSpec) { edParams = createNamedCurveSpec(((EdDSAGenParameterSpec) params).getName()); } else throw new InvalidAlgorithmParameterException("parameter object not a EdDSAParameterSpec"); this.random = random; initialized = true; } public KeyPair generateKeyPair() { if (!initialized) initialize(DEFAULT_STRENGTH, RandomSource.getInstance()); byte[] seed = new byte[edParams.getCurve().getField().getb()/8]; random.nextBytes(seed); EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(seed, edParams); EdDSAPublicKeySpec pubKey = new EdDSAPublicKeySpec(privKey.getA(), edParams); return new KeyPair(new EdDSAPublicKey(pubKey), new EdDSAPrivateKey(privKey)); } /** * Create an EdDSANamedCurveSpec from the provided curve name. The current * implementation fetches the pre-created curve spec from a table. * @param curveName the EdDSA named curve. * @return the specification for the named curve. * @throws InvalidAlgorithmParameterException if the named curve is unknown. */ protected EdDSANamedCurveSpec createNamedCurveSpec(String curveName) throws InvalidAlgorithmParameterException { EdDSANamedCurveSpec spec = EdDSANamedCurveTable.getByName(curveName); if (spec == null) { throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName); } return spec; } }