diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/gnu/javax/crypto/key/srp6 | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libjava/classpath/gnu/javax/crypto/key/srp6')
13 files changed, 2273 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java new file mode 100644 index 000000000..2c8e66fa2 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6Host.java @@ -0,0 +1,161 @@ +/* SRP6Host.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.hash.IMessageDigest; +import gnu.java.security.util.Util; +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.key.OutgoingMessage; +import gnu.javax.crypto.sasl.srp.SRP; +import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider; +import gnu.javax.crypto.sasl.srp.SRPRegistry; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +/** + * The implementation of the Host in the SRP-6 key agreement protocol. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRP6Host + extends SRP6KeyAgreement +{ + /** The user's ephemeral key pair. */ + private KeyPair hostKeyPair; + + /** The SRP password database. */ + private SRPAuthInfoProvider passwordDB; + + // default 0-arguments constructor + + protected void engineInit(final Map attributes) throws KeyAgreementException + { + rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS); + N = (BigInteger) attributes.get(SHARED_MODULUS); + if (N == null) + throw new KeyAgreementException("missing shared modulus"); + g = (BigInteger) attributes.get(GENERATOR); + if (g == null) + throw new KeyAgreementException("missing generator"); + final String md = (String) attributes.get(HASH_FUNCTION); + if (md == null || md.trim().length() == 0) + throw new KeyAgreementException("missing hash function"); + srp = SRP.instance(md); + passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB); + if (passwordDB == null) + throw new KeyAgreementException("missing SRP password database"); + } + + protected OutgoingMessage engineProcessMessage(final IncomingMessage in) + throws KeyAgreementException + { + switch (step) + { + case 0: + return computeSharedSecret(in); + default: + throw new IllegalStateException("unexpected state"); + } + } + + protected void engineReset() + { + hostKeyPair = null; + super.engineReset(); + } + + private OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + final String I = in.readString(); + final BigInteger A = in.readMPI(); + // get s and v for user identified by I + // ---------------------------------------------------------------------- + final Map credentials; + try + { + final Map userID = new HashMap(); + userID.put(Registry.SASL_USERNAME, I); + userID.put(SRPRegistry.MD_NAME_FIELD, srp.getAlgorithm()); + credentials = passwordDB.lookup(userID); + } + catch (IOException x) + { + throw new KeyAgreementException("computeSharedSecret()", x); + } + final BigInteger s = new BigInteger( + 1,Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD))); + final BigInteger v = new BigInteger( + 1, Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD))); + final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator(); + final Map attributes = new HashMap(); + if (rnd != null) + attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd); + attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N); + attributes.put(SRPKeyPairGenerator.GENERATOR, g); + attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v); + kpg.setup(attributes); + hostKeyPair = kpg.generate(); + final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY(); + final BigInteger u = uValue(A, B); // u = H(A | B) + // compute S = (Av^u) ^ b + final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX(); + final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N); + final byte[] sBytes = Util.trim(S); + final IMessageDigest hash = srp.newDigest(); + hash.update(sBytes, 0, sBytes.length); + K = new BigInteger(1, hash.digest()); + final OutgoingMessage result = new OutgoingMessage(); + result.writeMPI(s); + result.writeMPI(B); + complete = true; + return result; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java new file mode 100644 index 000000000..d3d27b381 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6KeyAgreement.java @@ -0,0 +1,141 @@ +/* SRP6KeyAgreement.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.hash.IMessageDigest; +import gnu.java.security.util.Util; + +import gnu.javax.crypto.key.BaseKeyAgreementParty; +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.sasl.srp.SRP; + +import java.math.BigInteger; + +/** + * The Secure Remote Password (SRP) key agreement protocol, also known as SRP-6, + * is designed by Thomas J. Wu (see references). The protocol, and its elements + * are described as follows: + * <pre> + * N A large safe prime (N = 2q+1, where q is prime) + * All arithmetic is done modulo N. + * g A generator modulo N + * s User's salt + * I Username + * p Cleartext Password + * H() One-way hash function + * ˆ (Modular) Exponentiation + * u Random scrambling parameter + * a,b Secret ephemeral values + * A,B Public ephemeral values + * x Private key (derived from p and s) + * v Password verifier + * + * The host stores passwords using the following formula: + * x = H(s | H(I ":" p)) (s is chosen randomly) + * v = gˆx (computes password verifier) + * + * The host then keeps {I, s, v} in its password database. + * + * The authentication protocol itself goes as follows: + * User -> Host: I, A = gˆa (identifies self, a = random number) + * Host -> User: s, B = 3v + gˆb (sends salt, b = random number) + * + * Both: u = H(A, B) + * + * User: x = H(s, p) (user enters password) + * User: S = (B - 3gˆx) ˆ (a + ux) (computes session key) + * User: K = H(S) + * + * Host: S = (Avˆu) ˆ b (computes session key) + * Host: K = H(S) + * </pre> + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public abstract class SRP6KeyAgreement + extends BaseKeyAgreementParty +{ + public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp6.ka.prng"; + public static final String SHARED_MODULUS = "gnu.crypto.srp6.ka.N"; + public static final String GENERATOR = "gnu.crypto.srp6.ka.g"; + public static final String HASH_FUNCTION = "gnu.crypto.srp6.ka.H"; + public static final String USER_IDENTITY = "gnu.crypto.srp6.ka.I"; + public static final String USER_PASSWORD = "gnu.crypto.srp6.ka.p"; + public static final String HOST_PASSWORD_DB = "gnu.crypto.srp6.ka.password.db"; + protected static final BigInteger THREE = BigInteger.valueOf(3L); + protected SRP srp; + protected BigInteger N; + protected BigInteger g; + /** The shared secret key. */ + protected BigInteger K; + + protected SRP6KeyAgreement() + { + super(Registry.SRP6_KA); + } + + protected byte[] engineSharedSecret() throws KeyAgreementException + { + return Util.trim(K); + } + + protected void engineReset() + { + srp = null; + N = null; + g = null; + K = null; + } + + protected BigInteger uValue(final BigInteger A, final BigInteger B) + { + final IMessageDigest hash = srp.newDigest(); + byte[] b; + b = Util.trim(A); + hash.update(b, 0, b.length); + b = Util.trim(B); + hash.update(b, 0, b.length); + return new BigInteger(1, hash.digest()); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java new file mode 100644 index 000000000..ec5cd7f17 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslClient.java @@ -0,0 +1,90 @@ +/* SRP6SaslClient.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.hash.IMessageDigest; +import gnu.java.security.util.Util; + +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.key.OutgoingMessage; + +import java.math.BigInteger; + +/** + * A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for the + * User (client side). + * <p> + * In this alternative, the exchange goes as follows: + * + * <pre> + * C -> S: I (identifies self) + * S -> C: N, g, s, B = 3v + gˆb (sends salt, b = random number) + * C -> S: A = gˆa (a = random number) + * </pre> + * + * <p> + * All elements are computed the same way as in the standard version. + * <p> + * Reference: + * <ol> + * <li><a + * href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt"> + * Secure Remote Password Authentication Mechanism</a><br> + * K. Burdis, R. Naffah.</li> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRP6SaslClient + extends SRP6TLSClient +{ + // default 0-arguments constructor + + protected OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + final OutgoingMessage result = super.computeSharedSecret(in); + final byte[] sBytes = Util.trim(K); + final IMessageDigest hash = srp.newDigest(); + hash.update(sBytes, 0, sBytes.length); + K = new BigInteger(1, hash.digest()); + return result; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java new file mode 100644 index 000000000..a4313f4d3 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6SaslServer.java @@ -0,0 +1,90 @@ +/* SRP6SaslServer.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.hash.IMessageDigest; +import gnu.java.security.util.Util; + +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.key.OutgoingMessage; + +import java.math.BigInteger; + +/** + * A variation of the SRP-6 protocol as used in the SASL-SRP mechanism, for the + * Host (server side). + * <p> + * In this alternative, the exchange goes as follows: + * + * <pre> + * C -> S: I (identifies self) + * S -> C: N, g, s, B = 3v + gˆb (sends salt, b = random number) + * C -> S: A = gˆa (a = random number) + * </pre> + * + * <p> + * All elements are computed the same way as in the standard version. + * <p> + * Reference: + * <ol> + * <li><a + * href="http://www.ietf.org/internet-drafts/draft-burdis-cat-srp-sasl-09.txt"> + * Secure Remote Password Authentication Mechanism</a><br> + * K. Burdis, R. Naffah.</li> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRP6SaslServer + extends SRP6TLSServer +{ + // default 0-arguments constructor + + protected OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + super.computeSharedSecret(in); + final byte[] sBytes = Util.trim(K); + final IMessageDigest hash = srp.newDigest(); + hash.update(sBytes, 0, sBytes.length); + K = new BigInteger(1, hash.digest()); + return null; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java new file mode 100644 index 000000000..c2459f620 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSClient.java @@ -0,0 +1,155 @@ +/* SRP6TLSClient.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.util.Util; +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.key.OutgoingMessage; +import gnu.javax.crypto.sasl.srp.SRP; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +/** + * A variation of the SRP6 key agreement protocol, for the client-side as + * proposed in <a + * href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using + * SRP for TLS Authentication</a>. The only difference between it and the SASL + * variant is that the shared secret is the entity <code>S</code> and not + * <code>H(S)</code>. + */ +public class SRP6TLSClient + extends SRP6KeyAgreement +{ + /** The user's identity. */ + private String I; + /** The user's cleartext password. */ + private byte[] p; + /** The user's ephemeral key pair. */ + private KeyPair userKeyPair; + + // default 0-arguments constructor + + protected void engineInit(final Map attributes) throws KeyAgreementException + { + rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS); + final String md = (String) attributes.get(HASH_FUNCTION); + if (md == null || md.trim().length() == 0) + throw new KeyAgreementException("missing hash function"); + srp = SRP.instance(md); + I = (String) attributes.get(USER_IDENTITY); + if (I == null) + throw new KeyAgreementException("missing user identity"); + p = (byte[]) attributes.get(USER_PASSWORD); + if (p == null) + throw new KeyAgreementException("missing user password"); + } + + protected OutgoingMessage engineProcessMessage(final IncomingMessage in) + throws KeyAgreementException + { + switch (step) + { + case 0: + return sendIdentity(in); + case 1: + return computeSharedSecret(in); + default: + throw new IllegalStateException("unexpected state"); + } + } + + protected void engineReset() + { + I = null; + p = null; + userKeyPair = null; + super.engineReset(); + } + + private OutgoingMessage sendIdentity(final IncomingMessage in) + throws KeyAgreementException + { + final OutgoingMessage result = new OutgoingMessage(); + result.writeString(I); + return result; + } + + protected OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + N = in.readMPI(); + g = in.readMPI(); + final BigInteger s = in.readMPI(); + final BigInteger B = in.readMPI(); + // generate an ephemeral keypair + final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator(); + final Map attributes = new HashMap(); + if (rnd != null) + attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd); + attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N); + attributes.put(SRPKeyPairGenerator.GENERATOR, g); + kpg.setup(attributes); + userKeyPair = kpg.generate(); + final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY(); + final BigInteger u = uValue(A, B); // u = H(A | B) + final BigInteger x; + try + { + x = new BigInteger(1, srp.computeX(Util.trim(s), I, p)); + } + catch (Exception e) + { + throw new KeyAgreementException("computeSharedSecret()", e); + } + // compute S = (B - 3g^x) ^ (a + ux) + final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX(); + final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))) + .modPow(a.add(u.multiply(x)), N); + K = S; + final OutgoingMessage result = new OutgoingMessage(); + result.writeMPI(A); + complete = true; + return result; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java new file mode 100644 index 000000000..42e3d9cb1 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6TLSServer.java @@ -0,0 +1,177 @@ +/* SRP6TLSServer.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.util.Util; +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.OutgoingMessage; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.sasl.srp.SRP; +import gnu.javax.crypto.sasl.srp.SRPAuthInfoProvider; +import gnu.javax.crypto.sasl.srp.SRPRegistry; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +/** + * A variation of the SRP6 key agreement protocol, for the server-side as + * proposed in <a + * href="http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-05.txt">Using + * SRP for TLS Authentication</a>. The only difference between it and the SASL + * variant is that the shared secret is the entity <code>S</code> and not + * <code>H(S)</code>. + */ +public class SRP6TLSServer + extends SRP6KeyAgreement +{ + /** The user's ephemeral key pair. */ + private KeyPair hostKeyPair; + /** The SRP password database. */ + private SRPAuthInfoProvider passwordDB; + + // default 0-arguments constructor + + protected void engineInit(final Map attributes) throws KeyAgreementException + { + rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS); + final String md = (String) attributes.get(HASH_FUNCTION); + if (md == null || md.trim().length() == 0) + throw new KeyAgreementException("missing hash function"); + srp = SRP.instance(md); + passwordDB = (SRPAuthInfoProvider) attributes.get(HOST_PASSWORD_DB); + if (passwordDB == null) + throw new KeyAgreementException("missing SRP password database"); + } + + protected OutgoingMessage engineProcessMessage(final IncomingMessage in) + throws KeyAgreementException + { + switch (step) + { + case 0: + return sendParameters(in); + case 1: + return computeSharedSecret(in); + default: + throw new IllegalStateException("unexpected state"); + } + } + + protected void engineReset() + { + hostKeyPair = null; + super.engineReset(); + } + + private OutgoingMessage sendParameters(final IncomingMessage in) + throws KeyAgreementException + { + final String I = in.readString(); + // get s and v for user identified by I + // ---------------------------------------------------------------------- + final Map credentials; + try + { + final Map userID = new HashMap(); + userID.put(Registry.SASL_USERNAME, I); + userID.put(SRPRegistry.MD_NAME_FIELD, srp.getAlgorithm()); + credentials = passwordDB.lookup(userID); + } + catch (IOException x) + { + throw new KeyAgreementException("computeSharedSecret()", x); + } + + final BigInteger s = new BigInteger( + 1, Util.fromBase64((String) credentials.get(SRPRegistry.SALT_FIELD))); + final BigInteger v = new BigInteger( + 1, Util.fromBase64((String) credentials.get(SRPRegistry.USER_VERIFIER_FIELD))); + final Map configuration; + try + { + final String mode = (String) credentials.get(SRPRegistry.CONFIG_NDX_FIELD); + configuration = passwordDB.getConfiguration(mode); + } + catch (IOException x) + { + throw new KeyAgreementException("computeSharedSecret()", x); + } + N = new BigInteger( + 1, Util.fromBase64((String) configuration.get(SRPRegistry.SHARED_MODULUS))); + g = new BigInteger( + 1, Util.fromBase64((String) configuration.get(SRPRegistry.FIELD_GENERATOR))); + // generate an ephemeral keypair + final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator(); + final Map attributes = new HashMap(); + if (rnd != null) + attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd); + attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N); + attributes.put(SRPKeyPairGenerator.GENERATOR, g); + attributes.put(SRPKeyPairGenerator.USER_VERIFIER, v); + kpg.setup(attributes); + hostKeyPair = kpg.generate(); + final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY(); + final OutgoingMessage result = new OutgoingMessage(); + result.writeMPI(N); + result.writeMPI(g); + result.writeMPI(s); + result.writeMPI(B); + return result; + } + + protected OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + final BigInteger A = in.readMPI(); + final BigInteger B = ((SRPPublicKey) hostKeyPair.getPublic()).getY(); + final BigInteger u = uValue(A, B); // u = H(A | B) + // compute S = (Av^u) ^ b + final BigInteger b = ((SRPPrivateKey) hostKeyPair.getPrivate()).getX(); + final BigInteger v = ((SRPPrivateKey) hostKeyPair.getPrivate()).getV(); + final BigInteger S = A.multiply(v.modPow(u, N)).modPow(b, N); + K = S; + complete = true; + return null; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java new file mode 100644 index 000000000..4a1e8dda9 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRP6User.java @@ -0,0 +1,163 @@ +/* SRP6User.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.hash.IMessageDigest; +import gnu.java.security.util.Util; +import gnu.javax.crypto.key.KeyAgreementException; +import gnu.javax.crypto.key.IncomingMessage; +import gnu.javax.crypto.key.OutgoingMessage; +import gnu.javax.crypto.sasl.srp.SRP; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Map; + +/** + * The implementation of the User in the SRP-6 protocol. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRP6User + extends SRP6KeyAgreement +{ + /** The user's identity. */ + private String I; + /** The user's cleartext password. */ + private byte[] p; + /** The user's ephemeral key pair. */ + private KeyPair userKeyPair; + + // default 0-arguments constructor + + protected void engineInit(final Map attributes) throws KeyAgreementException + { + rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS); + N = (BigInteger) attributes.get(SHARED_MODULUS); + if (N == null) + throw new KeyAgreementException("missing shared modulus"); + g = (BigInteger) attributes.get(GENERATOR); + if (g == null) + throw new KeyAgreementException("missing generator"); + final String md = (String) attributes.get(HASH_FUNCTION); + if (md == null || md.trim().length() == 0) + throw new KeyAgreementException("missing hash function"); + srp = SRP.instance(md); + I = (String) attributes.get(USER_IDENTITY); + if (I == null) + throw new KeyAgreementException("missing user identity"); + p = (byte[]) attributes.get(USER_PASSWORD); + if (p == null) + throw new KeyAgreementException("missing user password"); + } + + protected OutgoingMessage engineProcessMessage(final IncomingMessage in) + throws KeyAgreementException + { + switch (step) + { + case 0: + return sendIdentity(in); + case 1: + return computeSharedSecret(in); + default: + throw new IllegalStateException("unexpected state"); + } + } + + protected void engineReset() + { + I = null; + p = null; + userKeyPair = null; + super.engineReset(); + } + + private OutgoingMessage sendIdentity(final IncomingMessage in) + throws KeyAgreementException + { + // generate an ephemeral keypair + final SRPKeyPairGenerator kpg = new SRPKeyPairGenerator(); + final Map attributes = new HashMap(); + if (rnd != null) + attributes.put(SRPKeyPairGenerator.SOURCE_OF_RANDOMNESS, rnd); + attributes.put(SRPKeyPairGenerator.SHARED_MODULUS, N); + attributes.put(SRPKeyPairGenerator.GENERATOR, g); + kpg.setup(attributes); + userKeyPair = kpg.generate(); + final OutgoingMessage result = new OutgoingMessage(); + result.writeString(I); + result.writeMPI(((SRPPublicKey) userKeyPair.getPublic()).getY()); + return result; + } + + private OutgoingMessage computeSharedSecret(final IncomingMessage in) + throws KeyAgreementException + { + final BigInteger s = in.readMPI(); + final BigInteger B = in.readMPI(); + final BigInteger A = ((SRPPublicKey) userKeyPair.getPublic()).getY(); + final BigInteger u = uValue(A, B); // u = H(A | B) + final BigInteger x; + try + { + x = new BigInteger(1, srp.computeX(Util.trim(s), I, p)); + } + catch (Exception e) + { + throw new KeyAgreementException("computeSharedSecret()", e); + } + // compute S = (B - 3g^x) ^ (a + ux) + final BigInteger a = ((SRPPrivateKey) userKeyPair.getPrivate()).getX(); + final BigInteger S = B.subtract(THREE.multiply(g.modPow(x, N))) + .modPow(a.add(u.multiply(x)), N); + final byte[] sBytes = Util.trim(S); + final IMessageDigest hash = srp.newDigest(); + hash.update(sBytes, 0, sBytes.length); + K = new BigInteger(1, hash.digest()); + complete = true; + return null; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java new file mode 100644 index 000000000..fb8249e05 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPAlgorithm.java @@ -0,0 +1,131 @@ +/* SRPAlgorithm.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.javax.crypto.sasl.srp.SRPRegistry; + +import java.math.BigInteger; + +/** + * Utilities for use with SRP-6 based methods and protocols. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRPAlgorithm +{ + // lifted from draft-burdis-cat-srp-sasl-09 + public static final BigInteger N_2048 = new BigInteger( + "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050" + + "A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50" + + "E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B8" + + "55F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773B" + + "CA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748" + + "544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6" + + "AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB6" + + "94B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", 16); + public static final BigInteger N_1536 = new BigInteger( + "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D" + + "5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DC" + + "DF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC" + + "764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C486" + + "65772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E" + + "5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB", 16); + public static final BigInteger N_1280 = new BigInteger( + "D77946826E811914B39401D56A0A7843A8E7575D738C672A090AB1187D690DC4" + + "3872FC06A7B6A43F3B95BEAEC7DF04B9D242EBDC481111283216CE816E004B78" + + "6C5FCE856780D41837D95AD787A50BBE90BD3A9C98AC0F5FC0DE744B1CDE1891" + + "690894BC1F65E00DE15B4B2AA6D87100C9ECC2527E45EB849DEB14BB2049B163" + + "EA04187FD27C1BD9C7958CD40CE7067A9C024F9B7C5A0B4F5003686161F0605B", 16); + public static final BigInteger N_1024 = new BigInteger( + "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576" + + "D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD1" + + "5DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC" + + "68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3", 16); + public static final BigInteger N_768 = new BigInteger( + "B344C7C4F8C495031BB4E04FF8F84EE95008163940B9558276744D91F7CC9F40" + + "2653BE7147F00F576B93754BCDDF71B636F2099E6FFF90E79575F3D0DE694AFF" + + "737D9BE9713CEF8D837ADA6380B1093E94B6A529A8C6C2BE33E0867C60C3262B", 16); + public static final BigInteger N_640 = new BigInteger( + "C94D67EB5B1A2346E8AB422FC6A0EDAEDA8C7F894C9EEEC42F9ED250FD7F0046" + + "E5AF2CF73D6B2FA26BB08033DA4DE322E144E7A8E9B12A0E4637F6371F34A207" + + "1C4B3836CBEEAB15034460FAA7ADF483", 16); + public static final BigInteger N_512 = new BigInteger( + "D4C7F8A2B32C11B8FBA9581EC4BA4F1B04215642EF7355E37C0FC0443EF756EA" + + "2C6B8EEB755A1C723027663CAA265EF785B8FF6A9B35227A52D86633DBDFCA43", 16); + public static final BigInteger N_384 = new BigInteger( + "8025363296FB943FCE54BE717E0E2958A02A9672EF561953B2BAA3BAACC3ED57" + + "54EB764C7AB7184578C57D5949CCB41B", 16); + public static final BigInteger N_264 = new BigInteger( + "115B8B692E0E045692CF280B436735C77A5A9E8A9E7ED56C965F87DB5B2A2ECE3", 16); + private static final BigInteger ZERO = BigInteger.ZERO; + private static final BigInteger ONE = BigInteger.ONE; + private static final BigInteger TWO = BigInteger.valueOf(2L); + + /** Trivial constructor to enforce usage through class methods. */ + private SRPAlgorithm() + { + super(); + } + + public static void checkParams(final BigInteger N, final BigInteger g) + { + // 1. N should be at least 512-bit long + final int blen = N.bitLength(); + if (blen < SRPRegistry.MINIMUM_MODULUS_BITLENGTH) + throw new IllegalArgumentException("Bit length of N (" + + blen + + ") is too low. Should be at least " + + SRPRegistry.MINIMUM_MODULUS_BITLENGTH); + // 2. N should be a prime + if (! N.isProbablePrime(80)) + throw new IllegalArgumentException("N should be prime but isn't"); + // 3. N should be of the form 2*q + 1, where q is prime + final BigInteger q = N.subtract(ONE).divide(TWO); + if (! q.isProbablePrime(80)) + throw new IllegalArgumentException("(N-1)/2 should be prime but isn't"); + // 4. g**q should be -1 mod N + final BigInteger gq = g.modPow(q, N).add(ONE).mod(N); + if (gq.compareTo(ZERO) != 0) + throw new IllegalArgumentException("g**q should be -1 (mod N) but isn't"); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java new file mode 100644 index 000000000..72ce8d2cf --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKey.java @@ -0,0 +1,147 @@ +/* SRPKey.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.key.IKeyPairCodec; + +import java.io.Serializable; +import java.math.BigInteger; +import java.security.Key; + +/** + * An abstract representation of a base SRP ephemeral key. + * <p> + * This object encapsulates the two numbers: + * <ul> + * <li><b>N</b>: A large safe prime (N = 2q+1, where q is prime).</li> + * <li><b>g</b>: A generator modulo N.</li> + * </ul> + * <p> + * Note that in SRP, all arithmetic is done modulo N. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public abstract class SRPKey + implements Key, Serializable +{ + /** The public, Germaine prime, shared modulus. */ + protected final BigInteger N; + /** The generator. */ + protected final BigInteger g; + + protected SRPKey(BigInteger N, BigInteger g) + { + super(); + + this.N = N; + this.g = g; + } + + /** + * Returns the standard algorithm name for this key. + * + * @return the standard algorithm name for this key. + */ + public String getAlgorithm() + { + return Registry.SRP_KPG; + } + + /** @deprecated see getEncoded(int). */ + public byte[] getEncoded() + { + return getEncoded(IKeyPairCodec.RAW_FORMAT); + } + + /** + * Returns {@link Registry#RAW_ENCODING_SHORT_NAME} which is the sole format + * supported for this type of keys. + * + * @return {@link Registry#RAW_ENCODING_SHORT_NAME} ALWAYS. + */ + public String getFormat() + { + return Registry.RAW_ENCODING_SHORT_NAME; + } + + /** + * Returns the public shared modulus. + * + * @return <code>N</code>. + */ + public BigInteger getN() + { + return N; + } + + /** + * Returns the generator. + * + * @return <code>g</code>. + */ + public BigInteger getG() + { + return g; + } + + /** + * Returns <code>true</code> if the designated object is an instance of + * <code>SRPKey</code> and has the same SRP parameter values as this one. + * + * @param obj the other non-null SRP key to compare to. + * @return <code>true</code> if the designated object is of the same type + * and value as this one. + */ + public boolean equals(Object obj) + { + if (obj == null) + return false; + if (! (obj instanceof SRPKey)) + return false; + SRPKey that = (SRPKey) obj; + return N.equals(that.getN()) && g.equals(that.getG()); + } + + public abstract byte[] getEncoded(int format); +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java new file mode 100644 index 000000000..59e5bc943 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairGenerator.java @@ -0,0 +1,282 @@ +/* SRPKeyPairGenerator.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Configuration; +import gnu.java.security.Registry; +import gnu.java.security.key.IKeyPairGenerator; +import gnu.java.security.util.PRNG; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.SecureRandom; +import java.util.Map; +import java.util.logging.Logger; + +/** + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRPKeyPairGenerator + implements IKeyPairGenerator +{ + private static final Logger log = Logger.getLogger(SRPKeyPairGenerator.class.getName()); + private static final BigInteger ZERO = BigInteger.ZERO; + private static final BigInteger ONE = BigInteger.ONE; + private static final BigInteger TWO = BigInteger.valueOf(2L); + private static final BigInteger THREE = BigInteger.valueOf(3L); + /** Property name of the length (Integer) of the modulus (N) of an SRP key. */ + public static final String MODULUS_LENGTH = "gnu.crypto.srp.L"; + /** Property name of the Boolean indicating wether or not to use defaults. */ + public static final String USE_DEFAULTS = "gnu.crypto.srp.use.defaults"; + /** Property name of the modulus (N) of an SRP key. */ + public static final String SHARED_MODULUS = "gnu.crypto.srp.N"; + /** Property name of the generator (g) of an SRP key. */ + public static final String GENERATOR = "gnu.crypto.srp.g"; + /** Property name of the user's verifier (v) for a Server SRP key. */ + public static final String USER_VERIFIER = "gnu.crypto.srp.v"; + /** + * Property name of an optional {@link SecureRandom} instance to use. The + * default is to use a classloader singleton from {@link PRNG}. + */ + public static final String SOURCE_OF_RANDOMNESS = "gnu.crypto.srp.prng"; + /** Default value for the modulus length. */ + private static final int DEFAULT_MODULUS_LENGTH = 1024; + /** The optional {@link SecureRandom} instance to use. */ + private SecureRandom rnd = null; + /** Bit length of the shared modulus. */ + private int l; + /** The shared public modulus. */ + private BigInteger N; + /** The Field generator. */ + private BigInteger g; + /** The user's verifier MPI. */ + private BigInteger v; + /** Our default source of randomness. */ + private PRNG prng = null; + + // implicit 0-arguments constructor + + public String name() + { + return Registry.SRP_KPG; + } + + public void setup(Map attributes) + { + // do we have a SecureRandom, or should we use our own? + rnd = (SecureRandom) attributes.get(SOURCE_OF_RANDOMNESS); + N = (BigInteger) attributes.get(SHARED_MODULUS); + if (N != null) + { + l = N.bitLength(); + g = (BigInteger) attributes.get(GENERATOR); + if (g == null) + g = TWO; + SRPAlgorithm.checkParams(N, g); + } + else + { // generate or use default values for N and g + Boolean useDefaults = (Boolean) attributes.get(USE_DEFAULTS); + if (useDefaults == null) + useDefaults = Boolean.TRUE; + Integer L = (Integer) attributes.get(MODULUS_LENGTH); + l = DEFAULT_MODULUS_LENGTH; + if (useDefaults.equals(Boolean.TRUE)) + { + if (L != null) + { + l = L.intValue(); + switch (l) + { + case 512: + N = SRPAlgorithm.N_512; + break; + case 640: + N = SRPAlgorithm.N_640; + break; + case 768: + N = SRPAlgorithm.N_768; + break; + case 1024: + N = SRPAlgorithm.N_1024; + break; + case 1280: + N = SRPAlgorithm.N_1280; + break; + case 1536: + N = SRPAlgorithm.N_1536; + break; + case 2048: + N = SRPAlgorithm.N_2048; + break; + default: + throw new IllegalArgumentException( + "unknown default shared modulus bit length"); + } + g = TWO; + l = N.bitLength(); + } + } + else // generate new N and g + { + if (L != null) + { + l = L.intValue(); + if ((l % 256) != 0 || l < 512 || l > 2048) + throw new IllegalArgumentException( + "invalid shared modulus bit length"); + } + } + } + // are we using this generator on the server side, or the client side? + v = (BigInteger) attributes.get(USER_VERIFIER); + } + + public KeyPair generate() + { + if (N == null) + { + BigInteger[] params = generateParameters(); + BigInteger q = params[0]; + N = params[1]; + g = params[2]; + if (Configuration.DEBUG) + { + log.fine("q: " + q.toString(16)); + log.fine("N: " + N.toString(16)); + log.fine("g: " + g.toString(16)); + } + } + return (v != null ? hostKeyPair() : userKeyPair()); + } + + private synchronized BigInteger[] generateParameters() + { + // N A large safe prime (N = 2q+1, where q is prime) + // g A generator modulo N + BigInteger q, p, g; + byte[] qBytes = new byte[l / 8]; + do + { + do + { + nextRandomBytes(qBytes); + q = new BigInteger(1, qBytes); + q = q.setBit(0).setBit(l - 2).clearBit(l - 1); + } + while (! q.isProbablePrime(80)); + p = q.multiply(TWO).add(ONE); + } + while (p.bitLength() != l || ! p.isProbablePrime(80)); + // compute g. from FIPS-186, Appendix 4: e == 2 + BigInteger p_minus_1 = p.subtract(ONE); + g = TWO; + // Set h = any integer, where 1 < h < p - 1 and + // h differs from any value previously tried + for (BigInteger h = TWO; h.compareTo(p_minus_1) < 0; h = h.add(ONE)) + { + // Set g = h**2 mod p + g = h.modPow(TWO, p); + // If g = 1, go to step 3 + if (! g.equals(ONE)) + break; + } + return new BigInteger[] { q, p, g }; + } + + private KeyPair hostKeyPair() + { + byte[] bBytes = new byte[(l + 7) / 8]; + BigInteger b, B; + do + { + do + { + nextRandomBytes(bBytes); + b = new BigInteger(1, bBytes); + } + while (b.compareTo(ONE) <= 0 || b.compareTo(N) >= 0); + B = THREE.multiply(v).add(g.modPow(b, N)).mod(N); + } + while (B.compareTo(ZERO) == 0 || B.compareTo(N) >= 0); + KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, B }), + new SRPPrivateKey(new BigInteger[] { N, g, b, v })); + return result; + } + + private KeyPair userKeyPair() + { + byte[] aBytes = new byte[(l + 7) / 8]; + BigInteger a, A; + do + { + do + { + nextRandomBytes(aBytes); + a = new BigInteger(1, aBytes); + } + while (a.compareTo(ONE) <= 0 || a.compareTo(N) >= 0); + A = g.modPow(a, N); + } + while (A.compareTo(ZERO) == 0 || A.compareTo(N) >= 0); + KeyPair result = new KeyPair(new SRPPublicKey(new BigInteger[] { N, g, A }), + new SRPPrivateKey(new BigInteger[] { N, g, a })); + return result; + } + + private void nextRandomBytes(byte[] buffer) + { + if (rnd != null) + rnd.nextBytes(buffer); + else + getDefaultPRNG().nextBytes(buffer); + } + + private PRNG getDefaultPRNG() + { + if (prng == null) + prng = PRNG.getInstance(); + + return prng; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java new file mode 100644 index 000000000..b7cc53693 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPKeyPairRawCodec.java @@ -0,0 +1,334 @@ +/* SRPKeyPairRawCodec.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.key.IKeyPairCodec; + +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * An object that implements the {@link IKeyPairCodec} operations for the + * <i>Raw</i> format to use with SRP keypairs. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRPKeyPairRawCodec + implements IKeyPairCodec +{ + // implicit 0-arguments constructor + + public int getFormatID() + { + return RAW_FORMAT; + } + + /** + * Returns the encoded form of the designated SRP public key according to the + * <i>Raw</i> format supported by this library. + * <p> + * The <i>Raw</i> format for an SRP public key, in this implementation, is a + * byte sequence consisting of the following: + * <ol> + * <li>4-byte magic consisting of the value of the literal + * {@link Registry#MAGIC_RAW_SRP_PUBLIC_KEY},</li> + * <li>1-byte version consisting of the constant: 0x01,</li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>N</code> in internet order,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>N</code>, + * </li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>g</code>,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>g</code>, + * </li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>y</code>,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>y</code>, + * </li> + * </ol> + * + * @param key the key to encode. + * @return the <i>Raw</i> format encoding of the designated key. + * @throws IllegalArgumentException if the designated key is not an SRP one. + */ + public byte[] encodePublicKey(PublicKey key) + { + if (! (key instanceof SRPPublicKey)) + throw new IllegalArgumentException("key"); + SRPPublicKey srpKey = (SRPPublicKey) key; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // magic + baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]); + baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1]); + baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2]); + baos.write(Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3]); + // version + baos.write(0x01); + // N + byte[] buffer = srpKey.getN().toByteArray(); + int length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + // g + buffer = srpKey.getG().toByteArray(); + length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + // y + buffer = srpKey.getY().toByteArray(); + length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + return baos.toByteArray(); + } + + public PublicKey decodePublicKey(byte[] k) + { + // magic + if (k[0] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0] + || k[1] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[1] + || k[2] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[2] + || k[3] != Registry.MAGIC_RAW_SRP_PUBLIC_KEY[3]) + throw new IllegalArgumentException("magic"); + // version + if (k[4] != 0x01) + throw new IllegalArgumentException("version"); + int i = 5; + int l; + byte[] buffer; + // N + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger N = new BigInteger(1, buffer); + // g + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger g = new BigInteger(1, buffer); + // y + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger y = new BigInteger(1, buffer); + return new SRPPublicKey(N, g, y); + } + + /** + * Returns the encoded form of the designated SRP private key according to the + * <i>Raw</i> format supported by this library. + * <p> + * The <i>Raw</i> format for an SRP private key, in this implementation, is a + * byte sequence consisting of the following: + * <ol> + * <li>4-byte magic consisting of the value of the literal + * {@link Registry#MAGIC_RAW_SRP_PRIVATE_KEY},</li> + * <li>1-byte version consisting of the constant: 0x01,</li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>N</code> in internet order,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>N</code>, + * </li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>g</code>,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>g</code>, + * </li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>x</code>,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>x</code>, + * </li> + * <li>one byte which indicates whether the SRP parameter <code>v</code> is + * included in this encoding (value <code>0x01</code>) or not (value + * <code>0x00</code>).</li> + * <li>4-byte count of following bytes representing the SRP parameter + * <code>v</code>,</li> + * <li>n-bytes representation of a {@link BigInteger} obtained by invoking + * the <code>toByteArray()</code> method on the SRP parameter <code>v</code>, + * </li> + * </ol> + * + * @param key the key to encode. + * @return the <i>Raw</i> format encoding of the designated key. + * @throws IllegalArgumentException if the designated key is not an SRP one. + */ + public byte[] encodePrivateKey(PrivateKey key) + { + if (! (key instanceof SRPPrivateKey)) + throw new IllegalArgumentException("key"); + SRPPrivateKey srpKey = (SRPPrivateKey) key; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // magic + baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]); + baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1]); + baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2]); + baos.write(Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3]); + // version + baos.write(0x01); + // N + byte[] buffer = srpKey.getN().toByteArray(); + int length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + // g + buffer = srpKey.getG().toByteArray(); + length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + // x + buffer = srpKey.getX().toByteArray(); + length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + // v + if (srpKey.getV() != null) + { + baos.write(0x01); + buffer = srpKey.getV().toByteArray(); + length = buffer.length; + baos.write( length >>> 24); + baos.write((length >>> 16) & 0xFF); + baos.write((length >>> 8) & 0xFF); + baos.write( length & 0xFF); + baos.write(buffer, 0, length); + } + else + baos.write(0x00); + return baos.toByteArray(); + } + + public PrivateKey decodePrivateKey(byte[] k) + { + // magic + if (k[0] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0] + || k[1] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[1] + || k[2] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[2] + || k[3] != Registry.MAGIC_RAW_SRP_PRIVATE_KEY[3]) + throw new IllegalArgumentException("magic"); + // version + if (k[4] != 0x01) + throw new IllegalArgumentException("version"); + int i = 5; + int l; + byte[] buffer; + // N + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger N = new BigInteger(1, buffer); + // g + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger g = new BigInteger(1, buffer); + // x + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger x = new BigInteger(1, buffer); + // v + l = k[i++]; + if (l == 0x01) + { + l = k[i++] << 24 + | (k[i++] & 0xFF) << 16 + | (k[i++] & 0xFF) << 8 + | (k[i++] & 0xFF); + buffer = new byte[l]; + System.arraycopy(k, i, buffer, 0, l); + i += l; + BigInteger v = new BigInteger(1, buffer); + return new SRPPrivateKey(N, g, x, v); + } + return new SRPPrivateKey(N, g, x); + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java new file mode 100644 index 000000000..c2e13be82 --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPrivateKey.java @@ -0,0 +1,227 @@ +/* SRPPrivateKey.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.key.IKeyPairCodec; + +import java.math.BigInteger; +import java.security.PrivateKey; + +/** + * A representation of an SRP ephemeral private key. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRPPrivateKey + extends SRPKey + implements PrivateKey +{ + /** + * The private exponent for either the server or the client engaged in the SRP + * protocol exchange. + */ + private final BigInteger X; + /** + * The user's verifier (v) --for the server-- also computed at the client side + * as g.modPow(x, N), where x is the hashed output of the user name and + * password . + */ + private final BigInteger v; + + /** + * Public constructor for use from outside this package. + * + * @param N the public shared modulus. + * @param g the generator. + * @param x the private exponent of the ephemeral key. + */ + public SRPPrivateKey(BigInteger N, BigInteger g, BigInteger x) + { + this(N, g, x, null); + } + + /** + * Public constructor for use from outside this package. + * + * @param N the public shared modulus. + * @param g the generator. + * @param x the private exponent of the ephemeral key. + * @param v the user's verifier value (for the server side only). + */ + public SRPPrivateKey(BigInteger N, BigInteger g, BigInteger x, BigInteger v) + { + super(N, g); + + SRPAlgorithm.checkParams(N, g); + this.X = x; + this.v = v; + } + + /** + * Default constructor. Assumes N and g are already validated. + * + * @param params an array of either 3 or 4 values representing N, g, and + * either v and X for the server, or just X for the client. Those + * values represent the following: + * <ol> + * <li>v (server side): the user's verifier.</li> + * <li>X (both sides): the server's or client's ephemeral private + * exponent.</li> + * </ol> + */ + SRPPrivateKey(BigInteger[] params) + { + super(params[0], params[1]); + + if (params.length == 3) + { + X = params[2]; + v = null; + } + else if (params.length == 4) + { + X = params[2]; + v = params[3]; + } + else + throw new IllegalArgumentException("invalid number of SRP parameters"); + } + + /** + * A class method that takes the output of the <code>encodePrivateKey()</code> + * method of an SRP keypair codec object (an instance implementing + * {@link IKeyPairCodec} for DSS keys, and re-constructs an instance of this + * object. + * + * @param k the contents of a previously encoded instance of this object. + * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in + * <code>k</code>, to represent a valid encoding of an instance + * of this object. + * @throws IllegalArgumentException if the byte sequence does not represent a + * valid encoding of an instance of this object. + */ + public static SRPPrivateKey valueOf(byte[] k) + { + // check magic... + // we should parse here enough bytes to know which codec to use, and + // direct the byte array to the appropriate codec. since we only have one + // codec, we could have immediately tried it; nevertheless since testing + // one byte is cheaper than instatiating a codec that will fail we test + // the first byte before we carry on. + if (k[0] == Registry.MAGIC_RAW_SRP_PRIVATE_KEY[0]) + { + // it's likely to be in raw format. get a raw codec and hand it over + IKeyPairCodec codec = new SRPKeyPairRawCodec(); + return (SRPPrivateKey) codec.decodePrivateKey(k); + } + throw new IllegalArgumentException("magic"); + } + + /** + * Returns the private exponent of the key as a {@link BigInteger}. + * + * @return the private exponent of the key as a {@link BigInteger}. + */ + public BigInteger getX() + { + return X; + } + + /** + * Returns the user's verifier as a {@link BigInteger}. + * + * @return the user's verifier as a {@link BigInteger} if this is an SRP + * private key of a Host, or <code>null</code> if this is a private + * SRP key for a User. + */ + public BigInteger getV() + { + return v; + } + + /** + * Returns the encoded form of this private key according to the designated + * format. + * + * @param format the desired format identifier of the resulting encoding. + * @return the byte sequence encoding this key according to the designated + * format. + * @throws IllegalArgumentException if the format is not supported. + */ + public byte[] getEncoded(int format) + { + byte[] result; + switch (format) + { + case IKeyPairCodec.RAW_FORMAT: + result = new SRPKeyPairRawCodec().encodePrivateKey(this); + break; + default: + throw new IllegalArgumentException("format"); + } + return result; + } + + /** + * Returns <code>true</code> if the designated object is an instance of + * <code>SRPPrivateKey</code> and has the same SRP parameter values as this + * one. + * + * @param obj the other non-null SRP key to compare to. + * @return <code>true</code> if the designated object is of the same type + * and value as this one. + */ + public boolean equals(Object obj) + { + if (obj == null) + return false; + if (! (obj instanceof SRPPrivateKey)) + return false; + SRPPrivateKey that = (SRPPrivateKey) obj; + boolean result = super.equals(that) && X.equals(that.getX()); + if (v != null) + result = result && v.equals(that.getV()); + return result; + } +} diff --git a/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java new file mode 100644 index 000000000..2db13ff4c --- /dev/null +++ b/libjava/classpath/gnu/javax/crypto/key/srp6/SRPPublicKey.java @@ -0,0 +1,175 @@ +/* SRPPublicKey.java -- + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.crypto.key.srp6; + +import gnu.java.security.Registry; +import gnu.java.security.key.IKeyPairCodec; + +import java.math.BigInteger; +import java.security.PublicKey; + +/** + * A representation of an SRP ephemeral public key. + * <p> + * Reference: + * <ol> + * <li><a href="http://srp.stanford.edu/design.html">SRP Protocol Design</a><br> + * Thomas J. Wu.</li> + * </ol> + */ +public class SRPPublicKey + extends SRPKey + implements PublicKey +{ + /** + * The public exponent for either the server or the client engaged in the SRP + * protocol exchange. + */ + private final BigInteger Y; + + /** + * Public constructor for use from outside this package. + * + * @param N the public shared modulus. + * @param g the generator. + * @param Y the public exponent of the ephemeral key. + */ + public SRPPublicKey(BigInteger N, BigInteger g, BigInteger Y) + { + super(N, g); + + SRPAlgorithm.checkParams(N, g); + this.Y = Y; + } + + /** + * Default constructor. Assumes that N and g are already validated. + * + * @param params an array of 3 values representing N, g and Y; the latter + * being the client's or server's public exponent. + */ + SRPPublicKey(BigInteger[] params) + { + super(params[0], params[1]); + + this.Y = params[2]; + } + + /** + * A class method that takes the output of the <code>encodePublicKey()</code> + * method of an SRP keypair codec object (an instance implementing + * {@link IKeyPairCodec} for SRP keys, and re-constructs an instance of this + * object. + * + * @param k the contents of a previously encoded instance of this object. + * @throws ArrayIndexOutOfBoundsException if there is not enough bytes, in + * <code>k</code>, to represent a valid encoding of an instance + * of this object. + * @throws IllegalArgumentException if the byte sequence does not represent a + * valid encoding of an instance of this object. + */ + public static SRPPublicKey valueOf(byte[] k) + { + // check magic... + // we should parse here enough bytes to know which codec to use, and + // direct the byte array to the appropriate codec. since we only have one + // codec, we could have immediately tried it; nevertheless since testing + // one byte is cheaper than instatiating a codec that will fail we test + // the first byte before we carry on. + if (k[0] == Registry.MAGIC_RAW_SRP_PUBLIC_KEY[0]) + { + // it's likely to be in raw format. get a raw codec and hand it over + IKeyPairCodec codec = new SRPKeyPairRawCodec(); + return (SRPPublicKey) codec.decodePublicKey(k); + } + throw new IllegalArgumentException("magic"); + } + + /** + * Returns the public exponent of the key as a {@link BigInteger}. + * + * @return the public exponent of the key as a {@link BigInteger}. + */ + public BigInteger getY() + { + return Y; + } + + /** + * Returns the encoded form of this public key according to the designated + * format. + * + * @param format the desired format identifier of the resulting encoding. + * @return the byte sequence encoding this key according to the designated + * format. + * @throws IllegalArgumentException if the format is not supported. + */ + public byte[] getEncoded(int format) + { + byte[] result; + switch (format) + { + case IKeyPairCodec.RAW_FORMAT: + result = new SRPKeyPairRawCodec().encodePublicKey(this); + break; + default: + throw new IllegalArgumentException("format"); + } + return result; + } + + /** + * Returns <code>true</code> if the designated object is an instance of + * <code>SRPPublicKey</code>and has the same SRP parameter values as this + * one. + * + * @param obj the other non-null SRP key to compare to. + * @return <code>true</code> if the designated object is of the same type + * and value as this one. + */ + public boolean equals(Object obj) + { + if (obj == null) + return false; + if (! (obj instanceof SRPPublicKey)) + return false; + SRPPublicKey that = (SRPPublicKey) obj; + return super.equals(that) && Y.equals(that.getY()); + } +} |