?? any_elgamal_pkcs1signature.java
字號:
} /** * Terminates the update process and returns the signature bytes of * all the data signed so far. * <p> * <b>NOTES:</b> Sun's documentation talks about the bytes returned * being X.509-encoded. For this ElGamal/PKCS#1 implementation, they * conform to PKCS#1 section 10. Practically, the return value will * be formed by concatenating a leading <i>NULL</i> byte, a block type * <i>BT</i>, a padding block <i>PS</i>, another <i>NULL</i>byte, and * finally a data block <i>D</i>; * ie: * <pre> * return = 0x00 || BT || PS || 0x00 || D. * </pre> * For signing, <i>PKCS#1 block type 01</i> encryption-block formatting * scheme is employed. The block type <i>BT</i> is a single byte valued * 0x01 and the padding block <i>PS</i> is enough 0xFF bytes to make the * length of the complete Multi Precision Integer equal to the length * of the public modulus. The data block <i>D</i> consists of the MIC -- * Message Integrity Check, or message digest value-- and the MIC * algorithm ASN.1 encoded identifier. The formal syntax in ASN.1 * notation is: * <pre> * SEQUENCE { * digestAlgorithm AlgorithmIdentifier, * digest OCTET STRING * } * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } * </pre> * * @return the bytes of the signing operation's result. * @exception SignatureException if the engine is not initialised properly. */ protected byte[] engineSign() throws SignatureException { if (state != SIGN) throw new SignatureException( getAlgorithm() + ": Not initialized for signing"); BigInteger pkcs = makePKCS1(); // sign the padded message. BigInteger[] ab = new BigInteger[2]; ElGamalAlgorithm.sign(pkcs, ab, p, g, x, rng);/* // DER-encode the result. ASN1Value sig = new ASN1Sequence(new ASN1Value[] { new ASN1Integer(ab[0]), new ASN1Integer(ab[1]), }); return sig.derEncode();*/// byte[] aBytes = ab[0].toByteArray();// byte[] bBytes = ab[1].toByteArray();// byte[] signature = new byte[primeLen*2];// System.arraycopy(aBytes, 0, signature, primeLen-aBytes.length, aBytes.length);// System.arraycopy(bBytes, 0, signature, signature.length-bBytes.length, bBytes.length);// return signature; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { BI.toStream(ab[0], baos); BI.toStream(ab[1], baos); } catch (IOException e) { throw new SignatureException("BI.toStream() failed"); } return baos.toByteArray(); } /** * Terminates the update process and verifies that the passed signature * equals that of a generated one based on the updated data so far. * <p> * <b>NOTES:</b> Sun's documentation talks about the bytes received * being X.509-encoded. For this ElGamal/PKCS#1 implementation, the bytes * received are assumed to conform to PKCS#1 section 10, or have * been generated by a previous invocation of the <code>engineSign</code> * method. * * @param signature the signature bytes to be verified. * @return true if the signature was verified successfully, false * otherwise. * @exception SignatureException if the engine is not initialised * properly, the received signature data is improperly * encoded or of the wrong type, etc. */ protected boolean engineVerify(byte[] signature) throws SignatureException { if (state != VERIFY) throw new SignatureException( getAlgorithm() + ": Not initialized for verification"); BigInteger pkcs = makePKCS1();/* // BER-decode the signature. ASN1Value value = null; try { value = new BERDecoder().decode(signature); ASN1Sequence seq = (ASN1Sequence) value; BigInteger a = ((ASN1Integer) (seq.elementAt(0))).BigIntegerValue(); BigInteger b = ((ASN1Integer) (seq.elementAt(1))).BigIntegerValue(); return ElGamalAlgorithm.verify(pkcs, a, b, p, g, y); } catch (ASN1FormatException e) { throw new InvalidKeyException("ElGamal: ASN.1 signature could not be decoded."); } catch (ClassCastException e) { throw new InvalidKeyException("ElGamal: ASN.1 signature has unexpected format."); }*/// if (signature.length != primeLen*2)// return false;// byte[] temp = new byte[primeLen];// System.arraycopy(signature, 0, temp, 0, primeLen);// BigInteger a = new BigInteger(POSITIVE, temp);// System.arraycopy(signature, 0, temp, 0, primeLen);// BigInteger b = new BigInteger(POSITIVE, temp); ByteArrayInputStream bais = new ByteArrayInputStream(signature); BigInteger a, b; try { a = BI.fromStream(bais); b = BI.fromStream(bais); } catch (IOException e) { throw new SignatureException("BI.fromStream() failed"); } return ElGamalAlgorithm.verify(pkcs, a, b, p, g, y); } /** * <b>SPI</b>: Sets an algorithm-specific parameter. * <p> * ElGamal has one algorithm-specific parameter called "random", of type * java.util.Random. It specifies the source of random bits used for * generating the <i>k</i> values needed for signing. If this parameter * is not set when <code>initSign</code> is called, the result of * <code>new SecureRandom()</code> will be used. * <p> * You can set the "random" parameter using the following code: * <pre> * try { * elgamal.setParameter("random", random_number_generator); * } catch (InvalidParameterException e) { ... } * </pre> * <p> * This is not useful if the Signature object will only be used for * verification. * * @param param the string identifier of the parameter. * @param value the parameter value. * @exception InvalidParameterException if !(param.equals("random") && * value instanceof java.util.Random) */ protected void engineSetParameter(String param, Object value) { if (param.equals("random")) { if (!(value instanceof Random)) throw new InvalidParameterException( "value must be an instance of java.util.Random"); rng = (Random) value; return; } throw new InvalidParameterException(param); } /** * <b>SPI</b>: Returns an algorithm-specific parameter. * <p> * ElGamal has one algorithm-specific parameter called "random", as described * <a href="#engineSetParameter">above</a>. It is guaranteed to be a subclass * of java.util.Random. Calling this method with a <i>param</i> string * other than "random" will return null. * * @param param the string name of the parameter. * @return the object that represents the parameter value, or null if there * is none. */ protected Object engineGetParameter(String param) { if (param.equals("random")) return rng; return null; }// Own methods//............................................................................ /** * Returns a byte array consisting of a padded message digest value, * previously computed. This packet will be ElGamal-signed with the * private key of this object to act as an authentication for whatever * was digested. * <p> * As described in the <i>engineSign()</i> method above, the return * array will consist of: * <pre> * MSB LSB * 00 01 FF-1 ... FF-n 00 AID-1 ... AID-n 04 LL MD-1 ... MD-n * | BT |----- PS -----| |-- AlgorithmId --|------ digest ------| * </pre> * <p> * The <i>AID<i> bytes form the <i>AlgorithmIdentifier</i> token. * The OCTET STRING tag is <i>04</i> and <i>LL</i> is the length byte * (the number of bytes in the message digest proper, i.e. <i>n</i>). * <p> * Bytes <i>MD-1</i> to <i>MD-n</i> are the message digest value * of the material updated so far, thus completing the <i>digest</i> * token in the SEQUENCE described in <i>engineSign()</i> above. * * @return the result of the updating process framed in a PKCS#1 * type 01 block structure as a BigInteger. */ private BigInteger makePKCS1() { byte[] theMD = md.digest(); // stop hashing int mdl = theMD.length; // result has as many bytes as the prime byte[] r = new byte[primeLen]; r[1] = 0x01; // PKCS#1 encryption block type byte[] aid = getAlgorithmEncoding(); // get the AID bytes int aidl = aid.length;// int padLen = primeLen - 3 - aidl - mdl - 2; // put padding bytes int padLen = primeLen - 3 - aidl - mdl; // put padding bytes for (int i = 0; i < padLen; i++) r[2 + i] = (byte)0xFF; System.arraycopy(aid, 0, r, padLen + 3, aidl); // copy the AID bytes// r[primeLen - mdl - 2] = 0x04; // tag it as an OCTET STRING// r[primeLen - mdl - 1] = (byte) mdl; // and say how long it is System.arraycopy(theMD, 0, r, primeLen - mdl, mdl); // now the mdif (DEBUG && debuglevel >= 4) debug("PKCS#1 frame = " + Hex.dumpString(r)); return new BigInteger(r); // always positive because r[0] is 0 } /** * Returns the ASN.1 bytes of the <i>AlgorithmIdentifier</i> token described * in <code>engineSign()</code> method above. * * @return the <i>AlgorithmIdentifier</i> bytes. */ protected abstract byte[] getAlgorithmEncoding();}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -