package jenkins.security;

import hudson.scm.SCM;
import hudson.tasks.Builder;
import hudson.util.Secret;

import javax.annotation.CheckForNull;
import java.io.IOException;
import jenkins.slaves.JnlpSlaveAgentProtocol;

/**
 * Confidential information that gets stored as a singleton in Jenkins, mostly some random token value.
 *
 * <p>
 * The actual value is persisted via {@link ConfidentialStore}, but each use case that requires
 * a secret like this should use a separate {@link ConfidentialKey} instance so that one compromised
 * {@link ConfidentialKey} (say through incorrect usage and failure to protect it) shouldn't compromise
 * all the others.
 *
 * <p>
 * {@link ConfidentialKey} is ultimately a sequence of bytes,
 * but for convenience, a family of subclasses are provided to represent the secret in different formats.
 * See {@link HexStringConfidentialKey} and {@link HMACConfidentialKey} for example. In addition to the programming
 * ease, these use case specific subtypes make it harder for vulnerability to creep in by making it harder
 * for the secret to leak.
 *
 * <p>
 * The {@link ConfidentialKey} subtypes are expected to be used as a singleton, like {@link JnlpSlaveAgentProtocol#SLAVE_SECRET}.
 * For code that relies on XStream for persistence (such as {@link Builder}s, {@link SCM}s, and other fragment objects
 * around builds and jobs), {@link Secret} provides more convenient way of storing secrets.
 *
 * @author Kohsuke Kawaguchi
 * @see Secret
 * @since 1.498
 */
public abstract class ConfidentialKey {
    /**
     * Name of the key. This is used as the file name.
     */
    private final String id;

    protected ConfidentialKey(String id) {
        this.id = id;
    }

    protected @CheckForNull byte[] load() throws IOException {
        return ConfidentialStore.get().load(this);
    }

    protected void store(byte[] payload) throws IOException {
        ConfidentialStore.get().store(this,payload);
    }

    public String getId() {
        return id;
    }
}
