All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.schlichtherle.truezip.crypto.raes.RaesOutputStream Maven / Gradle / Ivy

/*
 * Copyright (C) 2005-2015 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package de.schlichtherle.truezip.crypto.raes;

import de.schlichtherle.truezip.crypto.CipherOutputStream;
import de.schlichtherle.truezip.crypto.param.KeyStrength;
import edu.umd.cs.findbugs.annotations.CreatesObligation;
import java.io.IOException;
import java.io.OutputStream;
import javax.annotation.CheckForNull;
import javax.annotation.WillCloseWhenClosed;
import javax.annotation.concurrent.NotThreadSafe;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.Mac;

/**
 * An {@link OutputStream} to produce a file with data ecnrypted according
 * to the Random Access Encryption Specification (RAES).
 *
 * @see    RaesReadOnlyFile
 * @author Christian Schlichtherle
 */
@NotThreadSafe
public abstract class RaesOutputStream extends CipherOutputStream {

    /**
     * Update the given KLAC with the given file {@code length} in
     * little endian order and finish it, writing the result to {@code buf}.
     * The KLAC must already have been initialized and updated with the
     * password bytes as retrieved according to PKCS #12.
     * The result is stored in {@code buf}, which must match the given
     * KLAC's output size.
     */
    static void klac(final Mac klac, long length, final byte[] buf) {
        for (int i = 0; i < 8; i++) {
            klac.update((byte) length);
            length >>= 8;
        }
        final int bufLength = klac.doFinal(buf, 0);
        assert bufLength == buf.length;
    }

    /**
     * Returns a new {@code RaesOutputStream}.
     *
     * @param  out the output stream to decorate for writing the ciphered data.
     * @param  param The {@link RaesParameters} used to determine and
     *         configure the type of RAES file created.
     *         If the run time class of this parameter matches multiple
     *         parameter interfaces, it is at the discretion of this
     *         implementation which one is picked and hence which type of
     *         RAES file is created.
     *         If you need more control over this, pass in an instance which's
     *         run time class just implements the
     *         {@link RaesParametersProvider} interface.
     *         Instances of this interface are queried to find RAES parameters
     *         which match a known RAES type.
     *         This algorithm is recursively applied.
     * @return A new {@code RaesOutputStream}.
     * @throws RaesParametersException if {@code param} is {@code null} or
     *         no suitable RAES parameters can be found.
     * @throws IOException on any I/O error.
     */
    @CreatesObligation
    public static RaesOutputStream getInstance(
            final @WillCloseWhenClosed OutputStream out, // TODO: Use a source instead!
            @CheckForNull RaesParameters param)
    throws IOException {
        if (null == out)
            throw new NullPointerException();
        while (null != param) {
            // Order is important here to support multiple interface implementations!
            if (param instanceof Type0RaesParameters) {
                return new Type0RaesOutputStream(out,
                        (Type0RaesParameters) param);
            } else if (param instanceof RaesParametersProvider) {
                param = ((RaesParametersProvider) param)
                        .get(RaesParameters.class);
            } else {
                break;
            }
        }
        throw new RaesParametersException("No suitable RAES parameters available!");
    }

    @CreatesObligation
    @edu.umd.cs.findbugs.annotations.SuppressWarnings("OBL_UNSATISFIED_OBLIGATION")
    RaesOutputStream(   @CheckForNull @WillCloseWhenClosed OutputStream out,
                        @CheckForNull BufferedBlockCipher cipher) {
        super(out, cipher);
    }

    /**
     * Returns the key strength which is actually used to encrypt the data of
     * the RAES file.
     */
    public abstract KeyStrength getKeyStrength();
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy