| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.rsa;  | 
 | 
 | 
 | 
import java.io.IOException;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.security.spec.AlgorithmParameterSpec;  | 
 | 
import java.security.spec.PSSParameterSpec;  | 
 | 
import java.security.spec.MGF1ParameterSpec;  | 
 | 
import java.security.interfaces.*;  | 
 | 
 | 
 | 
import java.util.Arrays;  | 
 | 
import java.util.Hashtable;  | 
 | 
 | 
 | 
import sun.security.util.*;  | 
 | 
import sun.security.jca.JCAUtil;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class RSAPSSSignature extends SignatureSpi { | 
 | 
 | 
 | 
    private static final boolean DEBUG = false;  | 
 | 
 | 
 | 
    // utility method for comparing digest algorithms  | 
 | 
      | 
 | 
    private boolean isDigestEqual(String stdAlg, String givenAlg) { | 
 | 
        if (stdAlg == null || givenAlg == null) return false;  | 
 | 
 | 
 | 
        if (givenAlg.indexOf("-") != -1) { | 
 | 
            return stdAlg.equalsIgnoreCase(givenAlg);  | 
 | 
        } else { | 
 | 
            if (stdAlg.equals("SHA-1")) { | 
 | 
                return (givenAlg.equalsIgnoreCase("SHA") | 
 | 
                        || givenAlg.equalsIgnoreCase("SHA1")); | 
 | 
            } else { | 
 | 
                StringBuilder sb = new StringBuilder(givenAlg);  | 
 | 
                  | 
 | 
                if (givenAlg.regionMatches(true, 0, "SHA", 0, 3)) { | 
 | 
                    givenAlg = sb.insert(3, "-").toString();  | 
 | 
                    return stdAlg.equalsIgnoreCase(givenAlg);  | 
 | 
                } else { | 
 | 
                    throw new ProviderException("Unsupported digest algorithm " | 
 | 
                            + givenAlg);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final byte[] EIGHT_BYTES_OF_ZEROS = new byte[8];  | 
 | 
 | 
 | 
    private static final Hashtable<String, Integer> DIGEST_LENGTHS =  | 
 | 
        new Hashtable<String, Integer>();  | 
 | 
    static { | 
 | 
        DIGEST_LENGTHS.put("SHA-1", 20); | 
 | 
        DIGEST_LENGTHS.put("SHA", 20); | 
 | 
        DIGEST_LENGTHS.put("SHA1", 20); | 
 | 
        DIGEST_LENGTHS.put("SHA-224", 28); | 
 | 
        DIGEST_LENGTHS.put("SHA224", 28); | 
 | 
        DIGEST_LENGTHS.put("SHA-256", 32); | 
 | 
        DIGEST_LENGTHS.put("SHA256", 32); | 
 | 
        DIGEST_LENGTHS.put("SHA-384", 48); | 
 | 
        DIGEST_LENGTHS.put("SHA384", 48); | 
 | 
        DIGEST_LENGTHS.put("SHA-512", 64); | 
 | 
        DIGEST_LENGTHS.put("SHA512", 64); | 
 | 
        DIGEST_LENGTHS.put("SHA-512/224", 28); | 
 | 
        DIGEST_LENGTHS.put("SHA512/224", 28); | 
 | 
        DIGEST_LENGTHS.put("SHA-512/256", 32); | 
 | 
        DIGEST_LENGTHS.put("SHA512/256", 32); | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private MessageDigest md;  | 
 | 
      | 
 | 
    private boolean digestReset = true;  | 
 | 
 | 
 | 
      | 
 | 
    private RSAPrivateKey privKey = null;  | 
 | 
      | 
 | 
    private RSAPublicKey pubKey = null;  | 
 | 
    // PSS parameters from signatures and keys respectively  | 
 | 
    private PSSParameterSpec sigParams = null;   | 
 | 
 | 
 | 
      | 
 | 
    private SecureRandom random;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public RSAPSSSignature() { | 
 | 
        this.md = null;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineInitVerify(PublicKey publicKey)  | 
 | 
            throws InvalidKeyException { | 
 | 
        if (!(publicKey instanceof RSAPublicKey)) { | 
 | 
            throw new InvalidKeyException("key must be RSAPublicKey"); | 
 | 
        }  | 
 | 
        this.pubKey = (RSAPublicKey) isValid((RSAKey)publicKey);  | 
 | 
        this.privKey = null;  | 
 | 
        resetDigest();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineInitSign(PrivateKey privateKey)  | 
 | 
            throws InvalidKeyException { | 
 | 
        engineInitSign(privateKey, null);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)  | 
 | 
            throws InvalidKeyException { | 
 | 
        if (!(privateKey instanceof RSAPrivateKey)) { | 
 | 
            throw new InvalidKeyException("key must be RSAPrivateKey"); | 
 | 
        }  | 
 | 
        this.privKey = (RSAPrivateKey) isValid((RSAKey)privateKey);  | 
 | 
        this.pubKey = null;  | 
 | 
        this.random =  | 
 | 
            (random == null? JCAUtil.getSecureRandom() : random);  | 
 | 
        resetDigest();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static boolean isCompatible(AlgorithmParameterSpec keyParams,  | 
 | 
            PSSParameterSpec sigParams) { | 
 | 
        if (keyParams == null) { | 
 | 
              | 
 | 
            return true;  | 
 | 
        }  | 
 | 
        if (!(keyParams instanceof PSSParameterSpec)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
          | 
 | 
        if (sigParams == null) { | 
 | 
            return true;  | 
 | 
        }  | 
 | 
        PSSParameterSpec pssKeyParams = (PSSParameterSpec) keyParams;  | 
 | 
          | 
 | 
        if (pssKeyParams.getSaltLength() > sigParams.getSaltLength()) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        PSSParameterSpec keyParams2 =  | 
 | 
            new PSSParameterSpec(pssKeyParams.getDigestAlgorithm(),  | 
 | 
                    pssKeyParams.getMGFAlgorithm(),  | 
 | 
                    pssKeyParams.getMGFParameters(),  | 
 | 
                    sigParams.getSaltLength(),  | 
 | 
                    pssKeyParams.getTrailerField());  | 
 | 
        PSSParameters ap = new PSSParameters();  | 
 | 
          | 
 | 
        try { | 
 | 
            ap.engineInit(keyParams2);  | 
 | 
            byte[] encoded = ap.engineGetEncoded();  | 
 | 
            ap.engineInit(sigParams);  | 
 | 
            byte[] encoded2 = ap.engineGetEncoded();  | 
 | 
            return Arrays.equals(encoded, encoded2);  | 
 | 
        } catch (Exception e) { | 
 | 
            if (DEBUG) { | 
 | 
                e.printStackTrace();  | 
 | 
            }  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private RSAKey isValid(RSAKey rsaKey) throws InvalidKeyException { | 
 | 
        try { | 
 | 
            AlgorithmParameterSpec keyParams = rsaKey.getParams();  | 
 | 
              | 
 | 
            if (!isCompatible(rsaKey.getParams(), this.sigParams)) { | 
 | 
                throw new InvalidKeyException  | 
 | 
                    ("Key contains incompatible PSS parameter values"); | 
 | 
            }  | 
 | 
              | 
 | 
            if (this.sigParams != null) { | 
 | 
                Integer hLen =  | 
 | 
                    DIGEST_LENGTHS.get(this.sigParams.getDigestAlgorithm());  | 
 | 
                if (hLen == null) { | 
 | 
                    throw new ProviderException("Unsupported digest algo: " + | 
 | 
                        this.sigParams.getDigestAlgorithm());  | 
 | 
                }  | 
 | 
                checkKeyLength(rsaKey, hLen, this.sigParams.getSaltLength());  | 
 | 
            }  | 
 | 
            return rsaKey;  | 
 | 
        } catch (SignatureException e) { | 
 | 
            throw new InvalidKeyException(e);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private PSSParameterSpec validateSigParams(AlgorithmParameterSpec p)  | 
 | 
            throws InvalidAlgorithmParameterException { | 
 | 
        if (p == null) { | 
 | 
            throw new InvalidAlgorithmParameterException  | 
 | 
                ("Parameters cannot be null"); | 
 | 
        }  | 
 | 
        if (!(p instanceof PSSParameterSpec)) { | 
 | 
            throw new InvalidAlgorithmParameterException  | 
 | 
                ("parameters must be type PSSParameterSpec"); | 
 | 
        }  | 
 | 
          | 
 | 
        PSSParameterSpec params = (PSSParameterSpec) p;  | 
 | 
        if (params == this.sigParams) return params;  | 
 | 
 | 
 | 
        RSAKey key = (this.privKey == null? this.pubKey : this.privKey);  | 
 | 
          | 
 | 
        if (key != null) { | 
 | 
            if (!isCompatible(key.getParams(), params)) { | 
 | 
                throw new InvalidAlgorithmParameterException  | 
 | 
                    ("Signature parameters does not match key parameters"); | 
 | 
            }  | 
 | 
        }  | 
 | 
          | 
 | 
        if (!(params.getMGFAlgorithm().equalsIgnoreCase("MGF1"))) { | 
 | 
            throw new InvalidAlgorithmParameterException("Only supports MGF1"); | 
 | 
 | 
 | 
        }  | 
 | 
        if (params.getTrailerField() != PSSParameterSpec.TRAILER_FIELD_BC) { | 
 | 
            throw new InvalidAlgorithmParameterException  | 
 | 
                ("Only supports TrailerFieldBC(1)"); | 
 | 
 | 
 | 
        }  | 
 | 
        String digestAlgo = params.getDigestAlgorithm();  | 
 | 
          | 
 | 
        if (key != null) { | 
 | 
            try { | 
 | 
                int hLen = DIGEST_LENGTHS.get(digestAlgo);  | 
 | 
                checkKeyLength(key, hLen, params.getSaltLength());  | 
 | 
            } catch (SignatureException e) { | 
 | 
                throw new InvalidAlgorithmParameterException(e);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return params;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void ensureInit() throws SignatureException { | 
 | 
        RSAKey key = (this.privKey == null? this.pubKey : this.privKey);  | 
 | 
        if (key == null) { | 
 | 
            throw new SignatureException("Missing key"); | 
 | 
        }  | 
 | 
        if (this.sigParams == null) { | 
 | 
              | 
 | 
            throw new SignatureException  | 
 | 
                ("Parameters required for RSASSA-PSS signatures"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static void checkKeyLength(RSAKey key, int digestLen,  | 
 | 
            int saltLen) throws SignatureException { | 
 | 
        if (key != null) { | 
 | 
            int keyLength = (getKeyLengthInBits(key) + 7) >> 3;  | 
 | 
            int minLength = Math.addExact(Math.addExact(digestLen, saltLen), 2);  | 
 | 
            if (keyLength < minLength) { | 
 | 
                throw new SignatureException  | 
 | 
                    ("Key is too short, need min " + minLength + " bytes"); | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private void resetDigest() { | 
 | 
        if (digestReset == false) { | 
 | 
            this.md.reset();  | 
 | 
            digestReset = true;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private byte[] getDigestValue() { | 
 | 
        digestReset = true;  | 
 | 
        return this.md.digest();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineUpdate(byte b) throws SignatureException { | 
 | 
        ensureInit();  | 
 | 
        this.md.update(b);  | 
 | 
        digestReset = false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineUpdate(byte[] b, int off, int len)  | 
 | 
            throws SignatureException { | 
 | 
        ensureInit();  | 
 | 
        this.md.update(b, off, len);  | 
 | 
        digestReset = false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected void engineUpdate(ByteBuffer b) { | 
 | 
        try { | 
 | 
            ensureInit();  | 
 | 
        } catch (SignatureException se) { | 
 | 
              | 
 | 
            throw new RuntimeException(se.getMessage());  | 
 | 
        }  | 
 | 
        this.md.update(b);  | 
 | 
        digestReset = false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected byte[] engineSign() throws SignatureException { | 
 | 
        ensureInit();  | 
 | 
        byte[] mHash = getDigestValue();  | 
 | 
        try { | 
 | 
            byte[] encoded = encodeSignature(mHash);  | 
 | 
            byte[] encrypted = RSACore.rsa(encoded, privKey, true);  | 
 | 
            return encrypted;  | 
 | 
        } catch (GeneralSecurityException e) { | 
 | 
            throw new SignatureException("Could not sign data", e); | 
 | 
        } catch (IOException e) { | 
 | 
            throw new SignatureException("Could not encode data", e); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    // verify the data and return the result. See JCA doc  | 
 | 
      | 
 | 
    @Override  | 
 | 
    protected boolean engineVerify(byte[] sigBytes) throws SignatureException { | 
 | 
        ensureInit();  | 
 | 
        try { | 
 | 
            if (sigBytes.length != RSACore.getByteLength(this.pubKey)) { | 
 | 
                throw new SignatureException  | 
 | 
                    ("Signature length not correct: got " | 
 | 
                    + sigBytes.length + " but was expecting "  | 
 | 
                    + RSACore.getByteLength(this.pubKey));  | 
 | 
            }  | 
 | 
            byte[] mHash = getDigestValue();  | 
 | 
            byte[] decrypted = RSACore.rsa(sigBytes, this.pubKey);  | 
 | 
            return decodeSignature(mHash, decrypted);  | 
 | 
        } catch (javax.crypto.BadPaddingException e) { | 
 | 
            // occurs if the app has used the wrong RSA public key  | 
 | 
            // or if sigBytes is invalid  | 
 | 
            // return false rather than propagating the exception for  | 
 | 
              | 
 | 
            return false;  | 
 | 
        } catch (IOException e) { | 
 | 
            throw new SignatureException("Signature encoding error", e); | 
 | 
        } finally { | 
 | 
            resetDigest();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private static int getKeyLengthInBits(RSAKey k) { | 
 | 
        if (k != null) { | 
 | 
            return k.getModulus().bitLength();  | 
 | 
        }  | 
 | 
        return -1;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private byte[] encodeSignature(byte[] mHash)  | 
 | 
        throws IOException, DigestException { | 
 | 
        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();  | 
 | 
        String mgfDigestAlgo;  | 
 | 
        if (mgfParams != null) { | 
 | 
            mgfDigestAlgo =  | 
 | 
                ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();  | 
 | 
        } else { | 
 | 
            mgfDigestAlgo = this.md.getAlgorithm();  | 
 | 
        }  | 
 | 
        try { | 
 | 
            int emBits = getKeyLengthInBits(this.privKey) - 1;  | 
 | 
            int emLen = (emBits + 7) >> 3;  | 
 | 
            int hLen = this.md.getDigestLength();  | 
 | 
            int dbLen = emLen - hLen - 1;  | 
 | 
            int sLen = this.sigParams.getSaltLength();  | 
 | 
 | 
 | 
            // maps DB into the corresponding region of EM and  | 
 | 
              | 
 | 
            byte[] em = new byte[emLen];  | 
 | 
 | 
 | 
            // step7 and some of step8  | 
 | 
            em[dbLen - sLen - 1] = (byte) 1;   | 
 | 
            em[em.length - 1] = (byte) 0xBC;   | 
 | 
 | 
 | 
            if (!digestReset) { | 
 | 
                throw new ProviderException("Digest should be reset"); | 
 | 
            }  | 
 | 
              | 
 | 
            this.md.update(EIGHT_BYTES_OF_ZEROS);  | 
 | 
            digestReset = false;   | 
 | 
            this.md.update(mHash);  | 
 | 
            if (sLen != 0) { | 
 | 
                  | 
 | 
                byte[] salt = new byte[sLen];  | 
 | 
                this.random.nextBytes(salt);  | 
 | 
                this.md.update(salt);  | 
 | 
 | 
 | 
                  | 
 | 
                System.arraycopy(salt, 0, em, dbLen - sLen, sLen);  | 
 | 
            }  | 
 | 
            // step6: generate H using M'  | 
 | 
            this.md.digest(em, dbLen, hLen);   | 
 | 
            digestReset = true;  | 
 | 
 | 
 | 
            // step7 and 8 are already covered by the code which setting up  | 
 | 
            // EM as above  | 
 | 
 | 
 | 
              | 
 | 
            MGF1 mgf1 = new MGF1(mgfDigestAlgo);  | 
 | 
            mgf1.generateAndXor(em, dbLen, hLen, dbLen, em, 0);  | 
 | 
 | 
 | 
            // step11: set the leftmost (8emLen - emBits) bits of the leftmost  | 
 | 
              | 
 | 
            int numZeroBits = (emLen << 3) - emBits;  | 
 | 
 | 
 | 
            if (numZeroBits != 0) { | 
 | 
                byte MASK = (byte) (0xff >>> numZeroBits);  | 
 | 
                em[0] = (byte) (em[0] & MASK);  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            return em;  | 
 | 
        } catch (NoSuchAlgorithmException e) { | 
 | 
            throw new IOException(e.toString());  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private boolean decodeSignature(byte[] mHash, byte[] em)  | 
 | 
            throws IOException { | 
 | 
        int hLen = mHash.length;  | 
 | 
        int sLen = this.sigParams.getSaltLength();  | 
 | 
        int emBits = getKeyLengthInBits(this.pubKey) - 1;  | 
 | 
        int emLen = (emBits + 7) >> 3;  | 
 | 
 | 
 | 
        // When key length is 8N+1 bits (N+1 bytes), emBits = 8N,  | 
 | 
        // emLen = N which is one byte shorter than em.length.  | 
 | 
          | 
 | 
        int emOfs = em.length - emLen;  | 
 | 
        if ((emOfs == 1) && (em[0] != 0)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        if (emLen < (hLen + sLen + 2)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        if (em[emOfs + emLen - 1] != (byte) 0xBC) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
        // step6: check if the leftmost (8emLen - emBits) bits of the leftmost  | 
 | 
          | 
 | 
        int numZeroBits = (emLen << 3) - emBits;  | 
 | 
 | 
 | 
        if (numZeroBits != 0) { | 
 | 
            byte MASK = (byte) (0xff << (8 - numZeroBits));  | 
 | 
            if ((em[emOfs] & MASK) != 0) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        String mgfDigestAlgo;  | 
 | 
        AlgorithmParameterSpec mgfParams = this.sigParams.getMGFParameters();  | 
 | 
        if (mgfParams != null) { | 
 | 
            mgfDigestAlgo =  | 
 | 
                ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();  | 
 | 
        } else { | 
 | 
            mgfDigestAlgo = this.md.getAlgorithm();  | 
 | 
        }  | 
 | 
          | 
 | 
        int dbLen = emLen - hLen - 1;  | 
 | 
        try { | 
 | 
            MGF1 mgf1 = new MGF1(mgfDigestAlgo);  | 
 | 
            mgf1.generateAndXor(em, emOfs + dbLen, hLen, dbLen,  | 
 | 
                    em, emOfs);  | 
 | 
        } catch (NoSuchAlgorithmException nsae) { | 
 | 
            throw new IOException(nsae.toString());  | 
 | 
        }  | 
 | 
 | 
 | 
        // step9: set the leftmost (8emLen - emBits) bits of the leftmost  | 
 | 
          | 
 | 
        if (numZeroBits != 0) { | 
 | 
            byte MASK = (byte) (0xff >>> numZeroBits);  | 
 | 
            em[emOfs] = (byte) (em[emOfs] & MASK);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        int i = emOfs;  | 
 | 
        for (; i < emOfs + (dbLen - sLen - 1); i++) { | 
 | 
            if (em[i] != 0) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (em[i] != 0x01) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
          | 
 | 
        this.md.update(EIGHT_BYTES_OF_ZEROS);  | 
 | 
        digestReset = false;  | 
 | 
        this.md.update(mHash);  | 
 | 
        if (sLen > 0) { | 
 | 
            this.md.update(em, emOfs + (dbLen - sLen), sLen);  | 
 | 
        }  | 
 | 
        byte[] digest2 = this.md.digest();  | 
 | 
        digestReset = true;  | 
 | 
 | 
 | 
          | 
 | 
        byte[] digestInEM = Arrays.copyOfRange(em, emOfs + dbLen,  | 
 | 
                emOfs + emLen - 1);  | 
 | 
        return MessageDigest.isEqual(digest2, digestInEM);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Deprecated  | 
 | 
    @Override  | 
 | 
    protected void engineSetParameter(String param, Object value)  | 
 | 
            throws InvalidParameterException { | 
 | 
        throw new UnsupportedOperationException("setParameter() not supported"); | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected void engineSetParameter(AlgorithmParameterSpec params)  | 
 | 
            throws InvalidAlgorithmParameterException { | 
 | 
        this.sigParams = validateSigParams(params);  | 
 | 
          | 
 | 
        if (!digestReset) { | 
 | 
            throw new ProviderException  | 
 | 
                ("Cannot set parameters during operations"); | 
 | 
        }  | 
 | 
        String newHashAlg = this.sigParams.getDigestAlgorithm();  | 
 | 
          | 
 | 
        if ((this.md == null) ||  | 
 | 
            !(this.md.getAlgorithm().equalsIgnoreCase(newHashAlg))) { | 
 | 
            try { | 
 | 
                this.md = MessageDigest.getInstance(newHashAlg);  | 
 | 
            } catch (NoSuchAlgorithmException nsae) { | 
 | 
                  | 
 | 
                throw new InvalidAlgorithmParameterException  | 
 | 
                    ("Unsupported digest algorithm " + | 
 | 
                     newHashAlg, nsae);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    @Deprecated  | 
 | 
    @Override  | 
 | 
    protected Object engineGetParameter(String param)  | 
 | 
            throws InvalidParameterException { | 
 | 
        throw new UnsupportedOperationException("getParameter() not supported"); | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected AlgorithmParameters engineGetParameters() { | 
 | 
        AlgorithmParameters ap = null;  | 
 | 
        if (this.sigParams != null) { | 
 | 
            try { | 
 | 
                ap = AlgorithmParameters.getInstance("RSASSA-PSS"); | 
 | 
                ap.init(this.sigParams);  | 
 | 
            } catch (GeneralSecurityException gse) { | 
 | 
                throw new ProviderException(gse.getMessage());  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return ap;  | 
 | 
    }  | 
 | 
}  |