
org.cryptomator.cryptolib.v1.FileHeaderImpl Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2016 Sebastian Stenzel and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the accompanying LICENSE.txt.
*
* Contributors:
* Sebastian Stenzel - initial API and implementation
*******************************************************************************/
package org.cryptomator.cryptolib.v1;
import com.google.common.base.Preconditions;
import org.cryptomator.cryptolib.api.FileHeader;
import org.cryptomator.cryptolib.common.DestroyableSecretKey;
import javax.security.auth.Destroyable;
import java.nio.ByteBuffer;
import java.util.Arrays;
class FileHeaderImpl implements FileHeader, Destroyable {
static final int NONCE_POS = 0;
static final int NONCE_LEN = 16;
static final int PAYLOAD_POS = 16;
static final int PAYLOAD_LEN = Payload.SIZE;
static final int MAC_POS = 56;
static final int MAC_LEN = 32;
static final int SIZE = NONCE_LEN + PAYLOAD_LEN + MAC_LEN;
private final byte[] nonce;
private final Payload payload;
FileHeaderImpl(byte[] nonce, Payload payload) {
if (nonce.length != NONCE_LEN) {
throw new IllegalArgumentException("Invalid nonce length. (was: " + nonce.length + ", required: " + NONCE_LEN + ")");
}
this.nonce = nonce;
this.payload = payload;
}
static FileHeaderImpl cast(FileHeader header) {
if (header instanceof FileHeaderImpl) {
return (FileHeaderImpl) header;
} else {
throw new IllegalArgumentException("Unsupported header type " + header.getClass());
}
}
public byte[] getNonce() {
return nonce;
}
public Payload getPayload() {
return payload;
}
@Override
public long getReserved() {
return payload.getReserved();
}
@Override
public void setReserved(long reserved) {
payload.setReserved(reserved);
}
@Override
public boolean isDestroyed() {
return payload.isDestroyed();
}
@Override
public void destroy() {
payload.destroy();
}
public static class Payload implements Destroyable {
static final int REVERSED_LEN = Long.BYTES;
static final int CONTENT_KEY_LEN = 32;
static final int SIZE = REVERSED_LEN + CONTENT_KEY_LEN;
private long reserved;
private final DestroyableSecretKey contentKey;
Payload(long reversed, byte[] contentKeyBytes) {
Preconditions.checkArgument(contentKeyBytes.length == CONTENT_KEY_LEN, "Invalid key length. (was: " + contentKeyBytes.length + ", required: " + CONTENT_KEY_LEN + ")");
this.reserved = reversed;
this.contentKey = new DestroyableSecretKey(contentKeyBytes, Constants.CONTENT_ENC_ALG);
}
static Payload decode(ByteBuffer cleartextPayloadBuf) {
Preconditions.checkArgument(cleartextPayloadBuf.remaining() == SIZE, "invalid payload buffer length");
long reserved = cleartextPayloadBuf.getLong();
byte[] contentKeyBytes = new byte[CONTENT_KEY_LEN];
cleartextPayloadBuf.get(contentKeyBytes);
return new Payload(reserved, contentKeyBytes);
}
ByteBuffer encode() {
ByteBuffer buf = ByteBuffer.allocate(SIZE);
buf.putLong(reserved);
buf.put(contentKey.getEncoded());
buf.flip();
return buf;
}
private long getReserved() {
return reserved;
}
private void setReserved(long reserved) {
this.reserved = reserved;
}
DestroyableSecretKey getContentKey() {
return contentKey;
}
@Override
public boolean isDestroyed() {
return contentKey.isDestroyed();
}
@Override
public void destroy() {
contentKey.destroy();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy