001/*
002 * Copyright 2015-2018 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns.dnssec.algorithms;
012
013import org.minidns.dnssec.DnssecValidationFailedException;
014import org.minidns.dnssec.SignatureVerifier;
015
016import java.security.InvalidKeyException;
017import java.security.KeyFactory;
018import java.security.NoSuchAlgorithmException;
019import java.security.PublicKey;
020import java.security.Signature;
021import java.security.SignatureException;
022
023public abstract class JavaSecSignatureVerifier implements SignatureVerifier {
024    private final KeyFactory keyFactory;
025    private final String signatureAlgorithm;
026
027    public JavaSecSignatureVerifier(String keyAlgorithm, String signatureAlgorithm) throws NoSuchAlgorithmException {
028        keyFactory = KeyFactory.getInstance(keyAlgorithm);
029        this.signatureAlgorithm = signatureAlgorithm;
030
031        // Verify signature algorithm to be valid
032        Signature.getInstance(signatureAlgorithm);
033    }
034
035    public KeyFactory getKeyFactory() {
036        return keyFactory;
037    }
038
039    @Override
040    public boolean verify(byte[] content, byte[] rrsigData, byte[] key) {
041        try {
042            PublicKey publicKey = getPublicKey(key);
043            Signature signature = Signature.getInstance(signatureAlgorithm);
044            signature.initVerify(publicKey);
045            signature.update(content);
046            return signature.verify(getSignature(rrsigData));
047        } catch (NoSuchAlgorithmException e) {
048            // We checked against this before, it should never happen!
049            throw new IllegalStateException();
050        } catch (InvalidKeyException | SignatureException | ArithmeticException e) {
051            throw new DnssecValidationFailedException("Validating signature failed", e);
052        }
053    }
054
055    protected abstract byte[] getSignature(byte[] rrsigData);
056
057    protected abstract PublicKey getPublicKey(byte[] key);
058}