You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2006/08/14 12:00:16 UTC
svn commit: r431317 - in
/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto:
CryptoProvider.java SHA1withDSA_SignatureImpl.java
Author: mloenko
Date: Mon Aug 14 03:00:14 2006
New Revision: 431317
URL: http://svn.apache.org/viewvc?rev=431317&view=rev
Log:
applied patch for HARMONY-1159
[classlib][security] crypto provider: SHA1withDSA implementation
Added:
incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
Modified:
incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java
Modified: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java?rev=431317&r1=431316&r2=431317&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/CryptoProvider.java Mon Aug 14 03:00:14 2006
@@ -14,51 +14,71 @@
* limitations under the License.
*/
-
package org.apache.harmony.security.provider.crypto;
-
import java.security.Provider;
import java.security.AccessController;
+import org.apache.harmony.security.provider.crypto.RandomBitsSupplier;
/**
- * Implementation of Provider for MessageDigest
+ * Implementation of Provider for SecureRandom, MessageDigest and Signature
* using a Secure Hash Algorithm, SHA-1;
- * see SECURE HASH STANDARD, FIPS PUB 180-2
- * (http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf) <BR>
+ * see SECURE HASH STANDARD, FIPS PUB 180-1 (http://www.itl.nist.gov/fipspubs/fip180-1.htm) <BR>
* <BR>
- * The implementation supports "SHA-1" algorithms described in
+ * The implementation supports "SHA1PRNG", "SHA-1" and "SHA1withDSA" algorithms described in
* JavaTM Cryptography Architecture, API Specification & Reference
*/
-
public final class CryptoProvider extends Provider {
-
/**
* Creates a Provider and puts parameters
*/
public CryptoProvider() {
- super("Crypto", 1.0, "HARMONY CryptoProvider");
+ super("Crypto", 1.0,
+ "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)");
+
+ // names of classes implementing services
+ final String MD_NAME = "org.apache.harmony.security.provider.crypto.SHA1_MessageDigestImpl";
+ final String SR_NAME = "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl";
+
+ final String SIGN_NAME = "org.apache.harmony.security.provider.crypto.SHA1withDSA_SignatureImpl";
- // names of classes implementing services
- final String MD_NAME =
- "org.apache.harmony.security.provider.crypto.SHA1_MessageDigestImpl";
-
- AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
-
- put("MessageDigest.SHA-1", MD_NAME);
- put("MessageDigest.SHA-1 ImplementedIn", "Software");
- put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
- put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+ final String SIGN_ALIAS = "SHA1withDSA";
- return null;
+ AccessController.doPrivileged(new java.security.PrivilegedAction() {
+
+ public Object run() {
+
+ put("MessageDigest.SHA-1", MD_NAME);
+ put("MessageDigest.SHA-1 ImplementedIn", "Software");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+ put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+
+ if (RandomBitsSupplier.isServiceAvailable()) {
+ put("SecureRandom.SHA1PRNG", SR_NAME);
+ put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
}
+
+ put("Signature.SHA1withDSA", SIGN_NAME);
+ put("Signature.SHA1withDSA ImplementedIn", "Software");
+ put("Alg.Alias.Signature.SHAwithDSA", SIGN_ALIAS);
+ put("Alg.Alias.Signature.DSAwithSHA1", SIGN_ALIAS);
+ put("Alg.Alias.Signature.SHA1/DSA", SIGN_ALIAS);
+ put("Alg.Alias.Signature.SHA/DSA", SIGN_ALIAS);
+ put("Alg.Alias.Signature.SHA-1/DSA", SIGN_ALIAS);
+ put("Alg.Alias.Signature.DSA", SIGN_ALIAS);
+ put("Alg.Alias.Signature.DSS", SIGN_ALIAS);
+
+ put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", SIGN_ALIAS);
+ put("Alg.Alias.Signature.1.2.840.10040.4.3", SIGN_ALIAS);
+ put("Alg.Alias.Signature.1.3.14.3.2.13", SIGN_ALIAS);
+ put("Alg.Alias.Signature.1.3.14.3.2.27", SIGN_ALIAS);
+
+ return null;
}
- );
+ });
}
}
Added: incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java?rev=431317&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1withDSA_SignatureImpl.java Mon Aug 14 03:00:14 2006
@@ -0,0 +1,434 @@
+/*
+ * Copyright 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.security.provider.crypto;
+
+import java.math.BigInteger;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Signature;
+
+import java.security.InvalidKeyException;
+import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
+
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAKey;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+
+import java.security.MessageDigest;
+
+public class SHA1withDSA_SignatureImpl extends Signature {
+
+ private MessageDigest msgDigest;
+
+ private DSAKey dsaKey;
+
+ /**
+ * The solo constructor.
+ */
+ public SHA1withDSA_SignatureImpl() throws NoSuchAlgorithmException {
+
+ super("SHA1withDSA");
+
+ msgDigest = MessageDigest.getInstance("SHA1");
+ }
+
+ /**
+ * Deprecated method.
+ *
+ * @return
+ * null
+ */
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ if (param == null) {
+ throw new NullPointerException("null argument");
+ }
+ return null;
+ }
+
+ /**
+ * Initializes this signature object with PrivateKey object
+ * passed as argument to the method.
+ *
+ * @params
+ * privateKey DSAPrivateKey object
+ * @throws
+ * InvalidKeyException if privateKey is not DSAPrivateKey object
+ */
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+
+ DSAParams params;
+
+ // parameters and private key
+ BigInteger p, q, g, x;
+
+ int n;
+
+ if (privateKey == null || !(privateKey instanceof DSAPrivateKey)) {
+ throw new InvalidKeyException(
+ "'privateKey' is not instanceof DSAPrivateKey");
+ }
+
+ params = ((DSAPrivateKey) privateKey).getParams();
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ x = ((DSAPrivateKey) privateKey).getX();
+
+ // checks described in DSA standard
+ n = p.bitLength();
+ if (p.compareTo(BigInteger.valueOf(1)) != 1 || n < 512 || n > 1024
+ || (n & 077) != 0) {
+ throw new InvalidKeyException("bad p");
+ }
+ if (q.signum() != 1 && q.bitLength() != 160) {
+ throw new InvalidKeyException("bad q");
+ }
+ if (x.signum() != 1 || x.compareTo(q) != -1) {
+ throw new InvalidKeyException("x is not positive or >= q");
+ }
+
+ dsaKey = (DSAKey) privateKey;
+
+ msgDigest.reset();
+ }
+
+ /**
+ * Initializes this signature object with PublicKey object
+ * passed as argument to the method.
+ *
+ * @params
+ * publicKey DSAPublicKey object
+ * @throws
+ * InvalidKeyException if publicKey is not DSAPublicKey object
+ */
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+
+ // parameters and public key
+ BigInteger p, q, g, y;
+
+ int n1;
+
+ if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
+ throw new InvalidKeyException(
+ "'publicKey' is not instanceof DSAPublicKey");
+ }
+
+ DSAParams params = ((DSAPublicKey) publicKey).getParams();
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ y = ((DSAPublicKey) publicKey).getY();
+
+ // checks described in DSA standard
+ n1 = p.bitLength();
+ if (p.compareTo(BigInteger.valueOf(1)) != 1 || n1 < 512 || n1 > 1024
+ || (n1 & 077) != 0) {
+ throw new InvalidKeyException("bad p");
+ }
+ if (q.signum() != 1 || q.bitLength() != 160) {
+ throw new InvalidKeyException("bad q");
+ }
+ if (y.signum() != 1) {
+ throw new InvalidKeyException("y is not positive");
+ }
+
+ dsaKey = (DSAKey) publicKey;
+
+ msgDigest.reset();
+ }
+
+ /*
+ * Deprecated method.
+ *
+ * @throws
+ * InvalidParameterException
+ */
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ if (param == null) {
+ throw new NullPointerException("null is passed for 'param'");
+ }
+ throw new InvalidParameterException("invalid parameter for this engine");
+ }
+
+ /**
+ * Returns signature bytes as byte array containing
+ * ASN1 representation for two BigInteger objects
+ * which is SEQUENCE of two INTEGERS.
+ * Length of sequence varies from less than 46 to 48.
+ *
+ * Resets object to the state it was in
+ * when previous call to either "initSign" method was called.
+ *
+ * @return
+ * byte array containing signature in ASN1 representation
+ * @throws
+ * SignatureException if object's state is not SIGN or
+ * signature algorithm cannot process data
+ */
+
+ protected byte[] engineSign() throws SignatureException {
+
+ // names of below BigIntegers are the same as they are defined in DSA standard
+ BigInteger r = null;
+ BigInteger s = null;
+ BigInteger k = null;
+
+ // parameters and private key
+ BigInteger p, q, g, x;
+
+ // BigInteger for message digest
+ BigInteger digestBI;
+
+ // various byte array being used in computing signature
+ byte randomBytes[];
+ byte digest[];
+ byte rBytes[], sBytes[], signature[];
+
+ int n, n1, n2;
+
+ DSAParams params;
+
+ if (appRandom == null) {
+ appRandom = new SecureRandom();
+ }
+
+ params = dsaKey.getParams();
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ x = ((DSAPrivateKey) dsaKey).getX();
+
+ // forming signature according algorithm described in chapter 5 of DSA standard
+
+ digestBI = new BigInteger(1, msgDigest.digest());
+
+ randomBytes = new byte[20];
+
+ for (;;) {
+
+ appRandom.nextBytes(randomBytes);
+
+ k = new BigInteger(1, randomBytes);
+ if (k.compareTo(q) != -1) {
+ continue;
+ }
+ r = g.modPow(k, p).mod(q);
+ if (r.signum() == 0) {
+ continue;
+ }
+
+ s = k.modInverse(q).multiply(digestBI.add(x.multiply(r)).mod(q))
+ .mod(q);
+
+ if (s.signum() != 0) {
+ break;
+ }
+ }
+
+ // forming signature's ASN1 representation which is SEQUENCE of two INTEGERs
+ //
+ rBytes = r.toByteArray();
+ n1 = rBytes.length;
+ if ((rBytes[0] & 0x80) != 0) {
+ n1++;
+ }
+ sBytes = s.toByteArray();
+ n2 = sBytes.length;
+ if ((sBytes[0] & 0x80) != 0) {
+ n2++;
+ }
+
+ signature = new byte[6 + n1 + n2]; // 48 is max. possible length of signature
+ signature[0] = (byte) 0x30; // ASN1 SEQUENCE tag
+ signature[1] = (byte) (4 + n1 + n2); // total length of two INTEGERs
+ signature[2] = (byte) 0x02; // ASN1 INTEGER tag
+ signature[3] = (byte) n1; // length of r
+ signature[4 + n1] = (byte) 0x02; // ASN1 INTEGER tag
+ signature[5 + n1] = (byte) n2; // length of s
+
+ if (n1 == rBytes.length) {
+ n = 4;
+ } else {
+ n = 5;
+ }
+ System.arraycopy(rBytes, 0, signature, n, rBytes.length);
+
+ if (n2 == sBytes.length) {
+ n = 6 + n1;
+ } else {
+ n = 7 + n1;
+ }
+ System.arraycopy(sBytes, 0, signature, n, sBytes.length);
+
+ return signature;
+ }
+
+ /**
+ * Updates data to sign or to verify.
+ *
+ * @params
+ * b byte to update
+ * @throws
+ * SignatureException if object was not initialized for signing or verifying
+ */
+ protected void engineUpdate(byte b) throws SignatureException {
+
+ msgDigest.update(b);
+ }
+
+ /**
+ * Updates data to sign or to verify.
+ *
+ * @params
+ * b byte array containg bytes to update
+ * @params
+ * off offset in byte array to start from
+ * @params
+ * len number of bytes to use for updating
+ * @throws
+ * SignatureException if object was not initialized for signing or verifying
+ */
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+
+ msgDigest.update(b, off, len);
+ }
+
+ private boolean checkSignature(byte[] sigBytes, int offset, int length)
+ throws SignatureException {
+
+ // names of below BigIntegers are the same as they are defined in DSA standard
+ BigInteger r, s, w;
+ BigInteger u1, u2, v;
+
+ // parameters and public key
+ BigInteger p, q, g, y;
+
+ DSAParams params;
+
+ int n1, n2;
+
+ byte bytes[];
+ byte digest[];
+
+ // checking up on signature's ASN1
+ try {
+ byte dummy;
+ n1 = sigBytes[offset + 3];
+ n2 = sigBytes[offset + n1 + 5];
+
+ if (sigBytes[offset + 0] != 0x30 || sigBytes[offset + 2] != 2
+ || sigBytes[offset + n1 + 4] != 2
+ || sigBytes[offset + 1] != (n1 + n2 + 4) || n1 > 21
+ || n2 > 21
+ || (length != 0 && (sigBytes[offset + 1] + 2) > length)) {
+ throw new SignatureException(
+ "signature bytes have invalid encoding");
+ }
+
+ dummy = sigBytes[5 + n1 + n2]; // to check length of sigBytes
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new SignatureException("bad argument: byte[] is too small");
+ }
+
+ digest = msgDigest.digest();
+
+ bytes = new byte[n1];
+ System.arraycopy(sigBytes, offset + 4, bytes, 0, n1);
+ r = new BigInteger(bytes);
+
+ bytes = new byte[n2];
+ System.arraycopy(sigBytes, offset + 6 + n1, bytes, 0, n2);
+ s = new BigInteger(bytes);
+
+ params = dsaKey.getParams();
+ p = params.getP();
+ q = params.getQ();
+ g = params.getG();
+ y = ((DSAPublicKey) dsaKey).getY();
+
+ // forming signature according algorithm described in chapter 6 of DSA standard
+
+ if (r.signum() != 1 || r.compareTo(q) != -1 || s.signum() != 1
+ || s.compareTo(q) != -1) {
+ return false;
+ }
+
+ w = s.modInverse(q);
+
+ u1 = (new BigInteger(1, digest)).multiply(w).mod(q);
+ u2 = r.multiply(w).mod(q);
+
+ v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
+
+ if (v.compareTo(r) != 0) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Verifies the signature bytes.
+ *
+ * @params
+ * sigBytes byte array with signature bytes to verify.
+ * @return
+ * true if signature bytes were verified, false otherwise
+ * @throws
+ * SignatureException if object's state is not VERIFY or
+ * signature format is not ASN1 representation or
+ * signature algorithm cannot process data
+ */
+ protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
+
+ if (sigBytes == null) {
+ throw new NullPointerException("null passed for 'sigBytes'");
+ }
+
+ return checkSignature(sigBytes, 0, 0);
+ }
+
+ /**
+ * Verifies the signature bytes.
+ *
+ * @params
+ * sigBytes byte array with signature bytes to verify.
+ * @params
+ * offset index in sigBytes to start from
+ * @params
+ * length number of bytes alotted for signature
+ * @return
+ * true if signature bytes were verified, false otherwise
+ * @throws
+ * SignatureException if object's state is not VERIFY or
+ * signature format is not ASN1 representation or
+ * signature algorithm cannot process data
+ */
+ protected boolean engineVerify(byte[] sigBytes, int offset, int length)
+ throws SignatureException {
+ return checkSignature(sigBytes, offset, length);
+ }
+}