forked from I2P_Developers/i2p.i2p
EdDSA:
- Implement one-shot methods in EdDSAEngine so we don't copy the data if all the data is available (ticket #1750) - Use EdDSA one-shot methods in DSAEngine - Fix API violation if EdDSAEngine object is reused for signing (ticket #1750) - Javadocs
This commit is contained in:
@@ -515,15 +515,20 @@ public final class DSAEngine {
|
||||
if (type == SigType.DSA_SHA1)
|
||||
return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
|
||||
|
||||
java.security.Signature jsig;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
|
||||
jsig = new EdDSAEngine(type.getDigestInstance());
|
||||
else
|
||||
jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(data, offset, len);
|
||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||
byte[] sigbytes = SigUtil.toJavaSig(signature);
|
||||
boolean rv;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA) {
|
||||
// take advantage of one-shot mode
|
||||
EdDSAEngine jsig = new EdDSAEngine(type.getDigestInstance());
|
||||
jsig.initVerify(pubKey);
|
||||
rv = jsig.verifyOneShot(data, offset, len, sigbytes);
|
||||
} else {
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(data, offset, len);
|
||||
rv = jsig.verify(sigbytes);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -563,15 +568,21 @@ public final class DSAEngine {
|
||||
if (type.getHashLen() != hashlen)
|
||||
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
||||
|
||||
String algo = getRawAlgo(type);
|
||||
java.security.Signature jsig;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
|
||||
jsig = new EdDSAEngine(); // Ignore algo, EdDSAKey includes a hash specification.
|
||||
else
|
||||
jsig = java.security.Signature.getInstance(algo);
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(hash.getData());
|
||||
boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
|
||||
byte[] sigbytes = SigUtil.toJavaSig(signature);
|
||||
boolean rv;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA) {
|
||||
// take advantage of one-shot mode
|
||||
// Ignore algo, EdDSAKey includes a hash specification.
|
||||
EdDSAEngine jsig = new EdDSAEngine();
|
||||
jsig.initVerify(pubKey);
|
||||
rv = jsig.verifyOneShot(hash.getData(), sigbytes);
|
||||
} else {
|
||||
String algo = getRawAlgo(type);
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(algo);
|
||||
jsig.initVerify(pubKey);
|
||||
jsig.update(hash.getData());
|
||||
rv = jsig.verify(sigbytes);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -606,15 +617,20 @@ public final class DSAEngine {
|
||||
if (type == SigType.DSA_SHA1)
|
||||
return altSignSHA1(data, offset, len, privateKey);
|
||||
|
||||
java.security.Signature jsig;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
|
||||
jsig = new EdDSAEngine(type.getDigestInstance());
|
||||
else
|
||||
jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
PrivateKey privKey = SigUtil.toJavaKey(privateKey);
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(data, offset, len);
|
||||
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||
byte[] sigbytes;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA) {
|
||||
// take advantage of one-shot mode
|
||||
EdDSAEngine jsig = new EdDSAEngine(type.getDigestInstance());
|
||||
jsig.initSign(privKey);
|
||||
sigbytes = jsig.signOneShot(data, offset, len);
|
||||
} else {
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(data, offset, len);
|
||||
sigbytes = jsig.sign();
|
||||
}
|
||||
return SigUtil.fromJavaSig(sigbytes, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,14 +665,20 @@ public final class DSAEngine {
|
||||
if (type.getHashLen() != hashlen)
|
||||
throw new IllegalArgumentException("type mismatch hash=" + hash.getClass() + " key=" + type);
|
||||
|
||||
java.security.Signature jsig;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA)
|
||||
jsig = new EdDSAEngine(); // Ignore algo, EdDSAKey includes a hash specification.
|
||||
else
|
||||
jsig = java.security.Signature.getInstance(algo);
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(hash.getData());
|
||||
return SigUtil.fromJavaSig(jsig.sign(), type);
|
||||
byte[] sigbytes;
|
||||
if (type.getBaseAlgorithm() == SigAlgo.EdDSA) {
|
||||
// take advantage of one-shot mode
|
||||
// Ignore algo, EdDSAKey includes a hash specification.
|
||||
EdDSAEngine jsig = new EdDSAEngine();
|
||||
jsig.initSign(privKey);
|
||||
sigbytes = jsig.signOneShot(hash.getData());
|
||||
} else {
|
||||
java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
|
||||
jsig.initSign(privKey, _context.random());
|
||||
jsig.update(hash.getData());
|
||||
sigbytes = jsig.sign();
|
||||
}
|
||||
return SigUtil.fromJavaSig(sigbytes, type);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -664,7 +664,6 @@ public final class SigUtil {
|
||||
* Only supports sigs up to about 65530 bytes. See code to fix BER encoding for this before you
|
||||
* add a SigType with bigger signatures.
|
||||
*
|
||||
* @param sig length must be even
|
||||
* @throws IllegalArgumentException if too big
|
||||
* @since 0.9.25, split out from sigBytesToASN1(byte[])
|
||||
*/
|
||||
|
@@ -2,6 +2,7 @@ package net.i2p.crypto.eddsa;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -9,6 +10,7 @@ import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.i2p.crypto.eddsa.math.Curve;
|
||||
@@ -16,21 +18,68 @@ import net.i2p.crypto.eddsa.math.GroupElement;
|
||||
import net.i2p.crypto.eddsa.math.ScalarOps;
|
||||
|
||||
/**
|
||||
* Signing and verification for EdDSA.
|
||||
*<p>
|
||||
* The EdDSA sign and verify algorithms do not interact well with
|
||||
* the Java Signature API, as one or more update() methods must be
|
||||
* called before sign() or verify(). Using the standard API,
|
||||
* this implementation must copy and buffer all data passed in
|
||||
* via update().
|
||||
*</p><p>
|
||||
* This implementation offers two ways to avoid this copying,
|
||||
* but only if all data to be signed or verified is available
|
||||
* in a single byte array.
|
||||
*</p><p>
|
||||
*Option 1:
|
||||
*</p><ol>
|
||||
*<li>Call initSign() or initVerify() as usual.
|
||||
*</li><li>Call setParameter(ONE_SHOT_MOE)
|
||||
*</li><li>Call update(byte[]) or update(byte[], int, int) exactly once
|
||||
*</li><li>Call sign() or verify() as usual.
|
||||
*</li><li>If doing additional one-shot signs or verifies with this object, you must
|
||||
* call setParameter(ONE_SHOT_MODE) each time
|
||||
*</li></ol>
|
||||
*
|
||||
*<p>
|
||||
*Option 2:
|
||||
*</p><ol>
|
||||
*<li>Call initSign() or initVerify() as usual.
|
||||
*</li><li>Call one of the signOneShot() or verifyOneShot() methods.
|
||||
*</li><li>If doing additional one-shot signs or verifies with this object,
|
||||
* just call signOneShot() or verifyOneShot() again.
|
||||
*</li></ol>
|
||||
*
|
||||
* @since 0.9.15
|
||||
* @author str4d
|
||||
*
|
||||
*/
|
||||
public final class EdDSAEngine extends Signature {
|
||||
private MessageDigest digest;
|
||||
private final ByteArrayOutputStream baos;
|
||||
private ByteArrayOutputStream baos;
|
||||
private EdDSAKey key;
|
||||
private boolean oneShotMode;
|
||||
private byte[] oneShotBytes;
|
||||
private int oneShotOffset;
|
||||
private int oneShotLength;
|
||||
|
||||
/**
|
||||
* To efficiently sign or verify data in one shot, pass this to setParameters()
|
||||
* after initSign() or initVerify() but BEFORE THE FIRST AND ONLY
|
||||
* update(data) or update(data, off, len). The data reference will be saved
|
||||
* and then used in sign() or verify() without copying the data.
|
||||
* Violate these rules and you will get a SignatureException.
|
||||
*
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public static final AlgorithmParameterSpec ONE_SHOT_MODE = new OneShotSpec();
|
||||
|
||||
private static class OneShotSpec implements AlgorithmParameterSpec {}
|
||||
|
||||
/**
|
||||
* No specific hash requested, allows any EdDSA key.
|
||||
*/
|
||||
public EdDSAEngine() {
|
||||
super("EdDSA");
|
||||
baos = new ByteArrayOutputStream(256);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,12 +91,21 @@ public final class EdDSAEngine extends Signature {
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
|
||||
/**
|
||||
* @since 0.9.25
|
||||
*/
|
||||
private void reset() {
|
||||
if (digest != null)
|
||||
digest.reset();
|
||||
baos.reset();
|
||||
if (baos != null)
|
||||
baos.reset();
|
||||
oneShotMode = false;
|
||||
oneShotBytes = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
|
||||
reset();
|
||||
if (privateKey instanceof EdDSAPrivateKey) {
|
||||
EdDSAPrivateKey privKey = (EdDSAPrivateKey) privateKey;
|
||||
key = privKey;
|
||||
@@ -61,21 +119,22 @@ public final class EdDSAEngine extends Signature {
|
||||
}
|
||||
} else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm()))
|
||||
throw new InvalidKeyException("Key hash algorithm does not match chosen digest");
|
||||
digestInitSign(privKey);
|
||||
} else {
|
||||
throw new InvalidKeyException("cannot identify EdDSA private key: " + privateKey.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
// Preparing for hash
|
||||
// r = H(h_b,...,h_2b-1,M)
|
||||
int b = privKey.getParams().getCurve().getField().getb();
|
||||
digest.update(privKey.getH(), b/8, b/4 - b/8);
|
||||
} else
|
||||
throw new InvalidKeyException("cannot identify EdDSA private key.");
|
||||
private void digestInitSign(EdDSAPrivateKey privKey) {
|
||||
// Preparing for hash
|
||||
// r = H(h_b,...,h_2b-1,M)
|
||||
int b = privKey.getParams().getCurve().getField().getb();
|
||||
digest.update(privKey.getH(), b/8, b/4 - b/8);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
|
||||
if (digest != null)
|
||||
digest.reset();
|
||||
baos.reset();
|
||||
|
||||
reset();
|
||||
if (publicKey instanceof EdDSAPublicKey) {
|
||||
key = (EdDSAPublicKey) publicKey;
|
||||
|
||||
@@ -88,34 +147,79 @@ public final class EdDSAEngine extends Signature {
|
||||
}
|
||||
} else if (!key.getParams().getHashAlgorithm().equals(digest.getAlgorithm()))
|
||||
throw new InvalidKeyException("Key hash algorithm does not match chosen digest");
|
||||
} else
|
||||
throw new InvalidKeyException("cannot identify EdDSA public key.");
|
||||
} else {
|
||||
throw new InvalidKeyException("cannot identify EdDSA public key: " + publicKey.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SignatureException if in one-shot mode
|
||||
*/
|
||||
@Override
|
||||
protected void engineUpdate(byte b) throws SignatureException {
|
||||
// We need to store the message because it is used in several hashes
|
||||
// XXX Can this be done more efficiently?
|
||||
if (oneShotMode)
|
||||
throw new SignatureException("unsupported in one-shot mode");
|
||||
if (baos == null)
|
||||
baos = new ByteArrayOutputStream(256);
|
||||
baos.write(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SignatureException if one-shot rules are violated
|
||||
*/
|
||||
@Override
|
||||
protected void engineUpdate(byte[] b, int off, int len)
|
||||
throws SignatureException {
|
||||
// We need to store the message because it is used in several hashes
|
||||
// XXX Can this be done more efficiently?
|
||||
baos.write(b, off, len);
|
||||
if (oneShotMode) {
|
||||
if (oneShotBytes != null)
|
||||
throw new SignatureException("update() already called");
|
||||
oneShotBytes = b;
|
||||
oneShotOffset = off;
|
||||
oneShotLength = len;
|
||||
} else {
|
||||
if (baos == null)
|
||||
baos = new ByteArrayOutputStream(256);
|
||||
baos.write(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] engineSign() throws SignatureException {
|
||||
try {
|
||||
return x_engineSign();
|
||||
} finally {
|
||||
reset();
|
||||
// must leave the object ready to sign again with
|
||||
// the same key, as required by the API
|
||||
EdDSAPrivateKey privKey = (EdDSAPrivateKey) key;
|
||||
digestInitSign(privKey);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] x_engineSign() throws SignatureException {
|
||||
Curve curve = key.getParams().getCurve();
|
||||
ScalarOps sc = key.getParams().getScalarOps();
|
||||
byte[] a = ((EdDSAPrivateKey) key).geta();
|
||||
|
||||
byte[] message = baos.toByteArray();
|
||||
byte[] message;
|
||||
int offset, length;
|
||||
if (oneShotMode) {
|
||||
if (oneShotBytes == null)
|
||||
throw new SignatureException("update() not called first");
|
||||
message = oneShotBytes;
|
||||
offset = oneShotOffset;
|
||||
length = oneShotLength;
|
||||
} else {
|
||||
if (baos == null)
|
||||
message = new byte[0];
|
||||
else
|
||||
message = baos.toByteArray();
|
||||
offset = 0;
|
||||
length = message.length;
|
||||
}
|
||||
// r = H(h_b,...,h_2b-1,M)
|
||||
byte[] r = digest.digest(message);
|
||||
digest.update(message, offset, length);
|
||||
byte[] r = digest.digest();
|
||||
|
||||
// r mod l
|
||||
// Reduces r from 64 bytes to 32 bytes
|
||||
@@ -128,7 +232,8 @@ public final class EdDSAEngine extends Signature {
|
||||
// S = (r + H(Rbar,Abar,M)*a) mod l
|
||||
digest.update(Rbyte);
|
||||
digest.update(((EdDSAPrivateKey) key).getAbyte());
|
||||
byte[] h = digest.digest(message);
|
||||
digest.update(message, offset, length);
|
||||
byte[] h = digest.digest();
|
||||
h = sc.reduce(h);
|
||||
byte[] S = sc.multiplyAndAdd(h, a, r);
|
||||
|
||||
@@ -141,6 +246,14 @@ public final class EdDSAEngine extends Signature {
|
||||
|
||||
@Override
|
||||
protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
|
||||
try {
|
||||
return x_engineVerify(sigBytes);
|
||||
} finally {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean x_engineVerify(byte[] sigBytes) throws SignatureException {
|
||||
Curve curve = key.getParams().getCurve();
|
||||
int b = curve.getField().getb();
|
||||
if (sigBytes.length != b/4)
|
||||
@@ -150,8 +263,24 @@ public final class EdDSAEngine extends Signature {
|
||||
digest.update(sigBytes, 0, b/8);
|
||||
digest.update(((EdDSAPublicKey) key).getAbyte());
|
||||
// h = H(Rbar,Abar,M)
|
||||
byte[] message = baos.toByteArray();
|
||||
byte[] h = digest.digest(message);
|
||||
byte[] message;
|
||||
int offset, length;
|
||||
if (oneShotMode) {
|
||||
if (oneShotBytes == null)
|
||||
throw new SignatureException("update() not called first");
|
||||
message = oneShotBytes;
|
||||
offset = oneShotOffset;
|
||||
length = oneShotLength;
|
||||
} else {
|
||||
if (baos == null)
|
||||
message = new byte[0];
|
||||
else
|
||||
message = baos.toByteArray();
|
||||
offset = 0;
|
||||
length = message.length;
|
||||
}
|
||||
digest.update(message, offset, length);
|
||||
byte[] h = digest.digest();
|
||||
|
||||
// h mod l
|
||||
h = key.getParams().getScalarOps().reduce(h);
|
||||
@@ -171,6 +300,140 @@ public final class EdDSAEngine extends Signature {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently sign all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data)
|
||||
* sig = sign()
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public byte[] signOneShot(byte[] data) throws SignatureException {
|
||||
return signOneShot(data, 0, data.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently sign all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data, off, len)
|
||||
* sig = sign()
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public byte[] signOneShot(byte[] data, int off, int len) throws SignatureException {
|
||||
oneShotMode = true;
|
||||
update(data, off, len);
|
||||
return sign();
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently verify all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data)
|
||||
* ok = verify(signature)
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public boolean verifyOneShot(byte[] data, byte[] signature) throws SignatureException {
|
||||
return verifyOneShot(data, 0, data.length, signature, 0, signature.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently verify all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data, off, len)
|
||||
* ok = verify(signature)
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public boolean verifyOneShot(byte[] data, int off, int len, byte[] signature) throws SignatureException {
|
||||
return verifyOneShot(data, off, len, signature, 0, signature.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently verify all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data)
|
||||
* ok = verify(signature, sigoff, siglen)
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public boolean verifyOneShot(byte[] data, byte[] signature, int sigoff, int siglen) throws SignatureException {
|
||||
return verifyOneShot(data, 0, data.length, signature, sigoff, siglen);
|
||||
}
|
||||
|
||||
/**
|
||||
* To efficiently verify all the data in one shot, if it is available,
|
||||
* use this method, which will avoid copying the data.
|
||||
*
|
||||
* Same as:
|
||||
*<pre>
|
||||
* setParameter(ONE_SHOT_MODE)
|
||||
* update(data, off, len)
|
||||
* ok = verify(signature, sigoff, siglen)
|
||||
*</pre>
|
||||
*
|
||||
* @throws SignatureException if update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
public boolean verifyOneShot(byte[] data, int off, int len, byte[] signature, int sigoff, int siglen) throws SignatureException {
|
||||
oneShotMode = true;
|
||||
update(data, off, len);
|
||||
return verify(signature, sigoff, siglen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidAlgorithmParameterException if spec is ONE_SHOT_MODE and update() already called
|
||||
* @see #ONE_SHOT_MODE
|
||||
* @since 0.9.25
|
||||
*/
|
||||
@Override
|
||||
protected void engineSetParameter(AlgorithmParameterSpec spec) throws InvalidAlgorithmParameterException {
|
||||
if (spec.equals(ONE_SHOT_MODE)) {
|
||||
if (oneShotBytes != null || baos != null && baos.size() > 0)
|
||||
throw new InvalidAlgorithmParameterException("update() already called");
|
||||
oneShotMode = true;
|
||||
} else {
|
||||
super.engineSetParameter(spec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated replaced with <a href="#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
|
||||
*/
|
||||
|
@@ -12,6 +12,13 @@ import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
|
||||
|
||||
/**
|
||||
* An EdDSA private key.
|
||||
*<p>
|
||||
* Warning: Private key encoding is not fully specified in the
|
||||
* current IETF draft. This implementation uses PKCS#8 encoding,
|
||||
* and is subject to change. See getEncoded().
|
||||
*</p><p>
|
||||
* Ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
|
||||
*</p>
|
||||
*
|
||||
* @since 0.9.15
|
||||
* @author str4d
|
||||
@@ -52,9 +59,7 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
|
||||
}
|
||||
|
||||
/**
|
||||
* This follows the spec at
|
||||
* https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
|
||||
* AND the docs from
|
||||
* This follows the docs from
|
||||
* java.security.spec.PKCS8EncodedKeySpec
|
||||
* quote:
|
||||
*<pre>
|
||||
@@ -78,6 +83,8 @@ public class EdDSAPrivateKey implements EdDSAKey, PrivateKey {
|
||||
* }
|
||||
*</pre>
|
||||
*
|
||||
* Ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
|
||||
*
|
||||
* Note that the private key encoding is not fully specified in the Josefsson draft version 04,
|
||||
* and the example could be wrong, as it's lacking Version and AlgorithmIdentifier.
|
||||
* This will hopefully be clarified in the next draft.
|
||||
|
@@ -12,6 +12,12 @@ import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
|
||||
|
||||
/**
|
||||
* An EdDSA public key.
|
||||
*<p>
|
||||
* Warning: Public key encoding is is based on the
|
||||
* current IETF draft, and is subject to change. See getEncoded().
|
||||
*</p><p>
|
||||
* Ref: https://tools.ietf.org/html/draft-josefsson-pkix-eddsa-04
|
||||
*</p>
|
||||
*
|
||||
* @since 0.9.15
|
||||
* @author str4d
|
||||
|
Reference in New Issue
Block a user