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

de.schlichtherle.truezip.key.SafeKeyProvider Maven / Gradle / Ivy

Go to download

The file system driver family for ZIP and related archive file types. Add the JAR artifact of this module to the run time class path to make its file system drivers available for service location in the client API modules.

There is a newer version: 7.7.10
Show newest version
/*
 * Copyright (C) 2005-2013 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package de.schlichtherle.truezip.key;

import de.schlichtherle.truezip.crypto.SuspensionPenalty;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.ThreadSafe;

/**
 * Provides the base functionality required to implement a "safe" key provider.
 * Each instance of this class maintains a single instance of the interface
 * {@link SafeKey}).
 * A clone of this key is returned on each call to {@link #getWriteKey}
 * and {@link #getReadKey}.
 *
 * @param    The type of the keys.
 * @author  Christian Schlichtherle
 */
@ThreadSafe
public abstract class SafeKeyProvider>
implements KeyProvider {

    /**
     * The minimum delay between subsequent attempts to verify a key in
     * milliseconds.
     * More specifically, this is the minimum delay between two calls to
     * {@link #getReadKey} by the same thread if the parameter {@code invalid}
     * is {@code true}.
     */
    public static final int MIN_KEY_RETRY_DELAY = SuspensionPenalty.MIN_KEY_RETRY_DELAY;

    private volatile @CheckForNull K key;

    private final ThreadLocal invalidated = new ThreadLocal();

    /**
     * Constructs a new safe key provider.
     */
    protected SafeKeyProvider() {
    }

    /**
     * {@inheritDoc}
     * 

* The implementation in {@link SafeKeyProvider} forwards the call to * {@link #retrieveWriteKey}. * * @throws UnknownKeyException If {@code retrieveWriteKey} throws * this exception or the secret key is still {@code null}. */ @Override public final K getWriteKey() throws UnknownKeyException { retrieveWriteKey(); return getNonNullKey(); } /** * Retrieves the secret key for the encryption of a protected resource. *

* Subsequent calls to this method may return the same object. * * @throws UnknownKeyException If the secret key is unknown. * At the subclasses discretion, this may mean that prompting for * the key has been disabled or cancelled by the user. * @see #getWriteKey */ protected abstract void retrieveWriteKey() throws UnknownKeyException; /** * {@inheritDoc} *

* The implementation in {@link SafeKeyProvider} forwards the call to * {@link #retrieveReadKey} and enforces a three seconds suspension penalty * if {@code invalid} is {@code true} before returning. * Because this method is final, this qualifies the implementation in * this class as a "safe" {@code KeyProvider} implementation, * even when subclassed. * * @throws UnknownKeyException If {@code retrieveReadKey} throws * this exception or the secret key is still {@code null}. */ @Override public final K getReadKey(boolean invalid) throws UnknownKeyException { if (invalid) invalidated.set(System.currentTimeMillis()); try { retrieveReadKey(invalid); } finally { final Long invalidated = this.invalidated.get(); SuspensionPenalty.enforce(null == invalidated ? 0 : invalidated); } return getNonNullKey(); } /** * Retrieves the secret key for the decryption of a protected resource. *

* Subsequent calls to this method may return the same object. * * @throws UnknownKeyException If the secret key is unknown. * At the subclasses discretion, this may mean that prompting for * the key has been disabled or cancelled by the user. * @see #getReadKey */ protected abstract void retrieveReadKey(boolean invalid) throws UnknownKeyException; private K getNonNullKey() throws UnknownKeyException { final K key = getKey(); if (null == key) throw new UnknownKeyException(); return key; } protected @CheckForNull K getKey() { final K key = this.key; return null == key ? null : key.clone(); } @Override public void setKey(final @CheckForNull K newKey) { final K oldKey = this.key; this.key = null == newKey ? null : newKey.clone(); if (null != oldKey) oldKey.reset(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy