org.diqube.ticket.TicketSignatureService.java Source code

Java tutorial

Introduction

Here is the source code for org.diqube.ticket.TicketSignatureService.java

Source

/**
 * diqube: Distributed Query Base.
 *
 * Copyright (C) 2015 Bastian Gloeckle
 *
 * This file is part of diqube.
 *
 * diqube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.diqube.ticket;

import java.nio.ByteBuffer;

import javax.inject.Inject;

import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.params.RSAKeyParameters;
import org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters;
import org.bouncycastle.crypto.signers.RSADigestSigner;
import org.diqube.context.AutoInstatiate;
import org.diqube.thrift.base.thrift.Ticket;
import org.diqube.util.Pair;

/**
 * Service that can sign {@link Ticket}s and verify integrity on those that have been signed already.
 *
 * @author Bastian Gloeckle
 */
@AutoInstatiate
public class TicketSignatureService {

    @Inject
    private TicketRsaKeyManager keyManager;

    /**
     * Checks if a {@link Ticket} has a valid signature.
     * 
     * @param deserializedTicket
     *          The result of {@link TicketUtil#deserialize(ByteBuffer)} of the serialized {@link Ticket}.
     * @return true if {@link Ticket} signature is valid.
     */
    public boolean isValidTicketSignature(Pair<Ticket, byte[]> deserializedTicket) {
        for (RSAKeyParameters pubKey : keyManager.getPublicValidationKeys()) {
            RSADigestSigner signer = new RSADigestSigner(new SHA256Digest());
            signer.init(false, pubKey);
            signer.update(deserializedTicket.getRight(), 0, deserializedTicket.getRight().length);
            if (signer.verifySignature(deserializedTicket.getLeft().getSignature()))
                return true;
        }
        return false;
    }

    /**
     * Calculates the signature of a ticket and updates the given {@link Ticket} object directly.
     * 
     * @throws IllegalStateException
     *           If ticket cannot be signed.
     */
    public void signTicket(Ticket ticket) throws IllegalStateException {
        byte[] serialized = TicketUtil.serialize(ticket);
        byte[] claimBytes = TicketUtil.deserialize(ByteBuffer.wrap(serialized)).getRight();

        RSAPrivateCrtKeyParameters signingKey = keyManager.getPrivateSigningKey();

        if (signingKey == null)
            throw new IllegalStateException(
                    "Cannot sign ticket because there is no private signing key available.");

        RSADigestSigner signer = new RSADigestSigner(new SHA256Digest());
        signer.init(true, signingKey);
        signer.update(claimBytes, 0, claimBytes.length);
        try {
            byte[] signature = signer.generateSignature();
            ticket.setSignature(signature);
        } catch (DataLengthException | CryptoException e) {
            throw new IllegalStateException("Cannot sign ticket", e);
        }
    }

}