From ed9d403281d57577d66428753ffba696ab20c9ce Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 24 Jan 2016 21:40:33 +0000 Subject: [PATCH] ElGamal: Implement key encoding --- core/java/src/net/i2p/crypto/SigUtil.java | 2 +- .../elgamal/impl/ElGamalPrivateKeyImpl.java | 59 ++++++++++++++++- .../elgamal/impl/ElGamalPublicKeyImpl.java | 65 ++++++++++++++++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/core/java/src/net/i2p/crypto/SigUtil.java b/core/java/src/net/i2p/crypto/SigUtil.java index 35bb307e6..0150256bb 100644 --- a/core/java/src/net/i2p/crypto/SigUtil.java +++ b/core/java/src/net/i2p/crypto/SigUtil.java @@ -716,7 +716,7 @@ public final class SigUtil { * @return the new index * @since 0.9.25 */ - private static int intToASN1(byte[] d, int idx, int val) { + public static int intToASN1(byte[] d, int idx, int val) { if (val < 0 || val > 65535) throw new IllegalArgumentException("fixme length " + val); if (val > 127) { diff --git a/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPrivateKeyImpl.java b/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPrivateKeyImpl.java index 9ca3672ac..0a03f3a2e 100644 --- a/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPrivateKeyImpl.java +++ b/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPrivateKeyImpl.java @@ -10,7 +10,9 @@ import javax.crypto.interfaces.DHPrivateKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPrivateKeySpec; +import static net.i2p.crypto.SigUtil.intToASN1; import net.i2p.crypto.elgamal.ElGamalPrivateKey; +import static net.i2p.crypto.elgamal.impl.ElGamalPublicKeyImpl.spaceFor; import net.i2p.crypto.elgamal.spec.ElGamalParameterSpec; import net.i2p.crypto.elgamal.spec.ElGamalPrivateKeySpec; @@ -93,7 +95,62 @@ public class ElGamalPrivateKeyImpl */ public byte[] getEncoded() { - return null; + byte[] pb = elSpec.getP().toByteArray(); + byte[] gb = elSpec.getG().toByteArray(); + byte[] xb = x.toByteArray(); + int seq3len = 2 + spaceFor(pb.length) + spaceFor(gb.length); + int seq2len = 8 + 1 + spaceFor(seq3len); + int seq1len = 1 + 3 + spaceFor(seq2len) + 1 + spaceFor(xb.length); + int totlen = 1 + spaceFor(seq1len); + byte[] rv = new byte[totlen]; + int idx = 0; + // sequence 1 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq1len); + + // version + rv[idx++] = 0x02; + rv[idx++] = 1; + rv[idx++] = 0; + + // Algorithm Identifier + // sequence 2 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq2len); + // OID: 1.3.14.7.2.1.1 + rv[idx++] = 0x06; + rv[idx++] = 6; + rv[idx++] = (1 * 40) + 3; + rv[idx++] = 14; + rv[idx++] = 7; + rv[idx++] = 2; + rv[idx++] = 1; + rv[idx++] = 1; + + // params + // sequence 3 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq3len); + // P + // integer + rv[idx++] = 0x02; + idx = intToASN1(rv, idx, pb.length); + System.arraycopy(pb, 0, rv, idx, pb.length); + idx += pb.length; + // G + // integer + rv[idx++] = 0x02; + idx = intToASN1(rv, idx, gb.length); + System.arraycopy(gb, 0, rv, idx, gb.length); + idx += gb.length; + + // the key + // octet string + rv[idx++] = 0x04; + idx = intToASN1(rv, idx, xb.length); + // BC puts an integer in the bit string, we're not going to do that + System.arraycopy(xb, 0, rv, idx, xb.length); + return rv; } public ElGamalParameterSpec getParameters() diff --git a/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPublicKeyImpl.java b/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPublicKeyImpl.java index c5cf71dd8..2510aef42 100644 --- a/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPublicKeyImpl.java +++ b/core/java/src/net/i2p/crypto/elgamal/impl/ElGamalPublicKeyImpl.java @@ -10,6 +10,7 @@ import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec; import javax.crypto.spec.DHPublicKeySpec; +import static net.i2p.crypto.SigUtil.intToASN1; import net.i2p.crypto.elgamal.ElGamalPublicKey; import net.i2p.crypto.elgamal.spec.ElGamalParameterSpec; import net.i2p.crypto.elgamal.spec.ElGamalPublicKeySpec; @@ -78,7 +79,69 @@ public class ElGamalPublicKeyImpl public byte[] getEncoded() { - return null; + byte[] pb = elSpec.getP().toByteArray(); + byte[] gb = elSpec.getG().toByteArray(); + byte[] yb = y.toByteArray(); + int seq3len = 2 + spaceFor(pb.length) + spaceFor(gb.length); + int seq2len = 8 + 1 + spaceFor(seq3len); + int seq1len = 1 + spaceFor(seq2len) + 1 + spaceFor(yb.length + 1); + int totlen = 1 + spaceFor(seq1len); + byte[] rv = new byte[totlen]; + int idx = 0; + // sequence 1 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq1len); + + // Algorithm Identifier + // sequence 2 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq2len); + // OID: 1.3.14.7.2.1.1 + rv[idx++] = 0x06; + rv[idx++] = 6; + rv[idx++] = (1 * 40) + 3; + rv[idx++] = 14; + rv[idx++] = 7; + rv[idx++] = 2; + rv[idx++] = 1; + rv[idx++] = 1; + + // params + // sequence 3 + rv[idx++] = 0x30; + idx = intToASN1(rv, idx, seq3len); + // P + // integer + rv[idx++] = 0x02; + idx = intToASN1(rv, idx, pb.length); + System.arraycopy(pb, 0, rv, idx, pb.length); + idx += pb.length; + // G + // integer + rv[idx++] = 0x02; + idx = intToASN1(rv, idx, gb.length); + System.arraycopy(gb, 0, rv, idx, gb.length); + idx += gb.length; + + // the key + // bit string + rv[idx++] = 0x03; + idx = intToASN1(rv, idx, yb.length + 1); + rv[idx++] = 0; // number of trailing unused bits + // BC puts an integer in the bit string, we're not going to do that + System.arraycopy(yb, 0, rv, idx, yb.length); + return rv; + } + + static int spaceFor(int val) { + int rv; + if (val > 255) + rv = 3; + else if (val > 127) + rv = 2; + else + rv = 1; + return rv + val; } public ElGamalParameterSpec getParameters()