any_rsa_pkcs1signature.java

来自「jpeg2000编解码」· Java 代码 · 共 494 行 · 第 1/2 页

JAVA
494
字号
     *              been generated with.     * @exception InvalidKeyException     *      If the key class does not implement java.security.interfaces.RSAPrivateKey     *      or     *      If the size of the minimal PKCS#1 frame generated by the     *      engineSign() method will be larger than the public key modulus.     */    protected void engineInitVerify (PublicKey key) throws InvalidKeyException {        if (!(key instanceof CryptixRSAPublicKey))            throw new InvalidKeyException(getAlgorithm() +                ": Not an RSA public key");        CryptixRSAPublicKey rsa = (CryptixRSAPublicKey) key;        n = rsa.getModulus();        exp = rsa.getExponent();        // It is unusual for an RSAPublicKey class to implement RSAFactors,        // because knowing p and q implies knowing the private key. Still,        // occasionally it is useful to verify a signature that you created,        // and this can be used to make that more efficient.        if (key instanceof RSAFactors) {            RSAFactors factors = (RSAFactors) key;            p = factors.getP();            q = factors.getQ();            u = factors.getInverseOfQModP();        }        md.reset();        // result will have as many bytes as the public modulus n        int mdl = md.digest().length;        int length = (n.bitLength() + 7) / 8;        int aidl = getAlgorithmEncoding().length;        int padLen = length - 3 - aidl - mdl;        if (padLen < 0) throw new            InvalidKeyException("Signer's public key modulus too short.");    }    /**     * Updates the data to be signed or verified, using one byte.     *     * @param  b  the byte to use for the update process.     * @exception SignatureException if the engine is not initialised properly.     */     protected void engineUpdate (byte b)    throws SignatureException {        if (state != VERIFY && state != SIGN)            throw new SignatureException(getAlgorithm() + ": Not initialized");        md.update(b);    }    /**     * Updates the data to be signed or verified, using the specified     * sub-array of bytes, starting at the specified offset.     *     * @param  in      the array of bytes.     * @param  offset  the offset to start from in <i>in</i>.     * @param  length  the number of bytes to use, starting at <i>offset</i>.     * @exception SignatureException if the engine is not initialised properly.     */              protected void engineUpdate (byte[] in, int offset, int length)    throws SignatureException {        if (state != VERIFY && state != SIGN)            throw new SignatureException(getAlgorithm() + ": Not initialized");        md.update(in, offset, length);    }    /**     * 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 RSA/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 RSA 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 signature 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");        long t = 0;if (DEBUG && debuglevel >= 7) t = System.currentTimeMillis();        BigInteger pkcs = makePKCS1();        BigInteger result = RSAAlgorithm.rsa(pkcs, n, exp, p, q, u);if (DEBUG && debuglevel >= 7) {    t = System.currentTimeMillis() - t;    debug(" ...engineSign() completed in "+t+" ms.");}        return result.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 RSA/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");        long t = 0;if (DEBUG && debuglevel >= 7) t = System.currentTimeMillis();        // if we generated it, it's a positive BI        BigInteger M = new BigInteger(1,signature);        BigInteger computed = RSAAlgorithm.rsa(M, n, exp, p, q, u);        BigInteger actual = makePKCS1();        boolean ok = computed.equals(actual);if (DEBUG && debuglevel >= 7) {    t = System.currentTimeMillis() - t;    debug(" ...engineVerify() completed in "+t+" ms.");    if (!ok) {        debug("   Computed: " + Hex.dumpString(computed.toByteArray()));        debug("     Actual: " + Hex.dumpString(actual.toByteArray()));    }}        return ok;    }    protected void engineSetParameter(String param, Object value)    throws InvalidParameterException {        throw new InvalidParameterException(getAlgorithm() + ": " + param);    }    protected Object engineGetParameter(String param)    throws InvalidParameterException {        throw new InvalidParameterException(getAlgorithm() + ": " + param);    }// Own methods//...........................................................................    /**     * Returns a byte array consisting of a padded message digest value,     * previously computed. This packet will be RSA-encrypted 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.     * @exception SignatureException If the length of the minimal PKCS#1 frame     *      generated by this method will be longer than the public key modulus.     */    private BigInteger makePKCS1() throws SignatureException {        byte[] theMD = md.digest();                           // stop hashing        int mdl = theMD.length;        // result has as many bytes as the public modulus        int length = (n.bitLength() + 7) / 8;        byte[] r = new byte[length];        r[1] = 0x01;                          // PKCS#1 encryption block type        byte[] aid = getAlgorithmEncoding();             // get the AID bytes        int aidl = aid.length;//        int padLen = length - 3 - aidl - mdl - 2;        // put padding bytes        int padLen = length - 3 - aidl - mdl;            // put padding bytes        if (padLen < 0)            throw new SignatureException("Signer's public key modulus too short.");        for (int i = 0; i < padLen;) r[2 + i++] = (byte) 0xFF;        System.arraycopy(aid, 0, r, padLen + 3, aidl);   // copy the AID bytes        // the next 2 bytes are now part of the subclass//        r[length - mdl - 2] = 0x04;              // tag it as an OCTET STRING//        r[length - mdl - 1] = (byte) mdl;           // and say how long it is        System.arraycopy(theMD, 0, r, length - mdl, mdl); // now the md per seif (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();}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?