001/*
002 * Copyright 2015-2024 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.DnssecValidationFailedException.DataMalformedException;
015import org.minidns.dnssec.DnssecValidationFailedException.DnssecInvalidKeySpecException;
016import org.minidns.dnssec.SignatureVerifier;
017import org.minidns.record.DNSKEY;
018import org.minidns.record.RRSIG;
019
020import java.security.InvalidKeyException;
021import java.security.KeyFactory;
022import java.security.NoSuchAlgorithmException;
023import java.security.PublicKey;
024import java.security.Signature;
025import java.security.SignatureException;
026
027public abstract class JavaSecSignatureVerifier implements SignatureVerifier {
028    private final KeyFactory keyFactory;
029    private final String signatureAlgorithm;
030
031    public JavaSecSignatureVerifier(String keyAlgorithm, String signatureAlgorithm) throws NoSuchAlgorithmException {
032        keyFactory = KeyFactory.getInstance(keyAlgorithm);
033        this.signatureAlgorithm = signatureAlgorithm;
034
035        // Verify signature algorithm to be valid
036        Signature.getInstance(signatureAlgorithm);
037    }
038
039    public KeyFactory getKeyFactory() {
040        return keyFactory;
041    }
042
043    @Override
044    public boolean verify(byte[] content, RRSIG rrsig, DNSKEY key) throws DnssecValidationFailedException {
045        try {
046            PublicKey publicKey = getPublicKey(key);
047            Signature signature = Signature.getInstance(signatureAlgorithm);
048            signature.initVerify(publicKey);
049            signature.update(content);
050            return signature.verify(getSignature(rrsig));
051        } catch (NoSuchAlgorithmException e) {
052            // We checked against this before, it should never happen!
053            throw new AssertionError(e);
054        } catch (InvalidKeyException | SignatureException | ArithmeticException e) {
055            throw new DnssecValidationFailedException("Validating signature failed", e);
056        }
057    }
058
059    protected abstract byte[] getSignature(RRSIG rrsig) throws DataMalformedException;
060
061    protected abstract PublicKey getPublicKey(DNSKEY key) throws DataMalformedException, DnssecInvalidKeySpecException;
062}