CryptoKit.java
package space.sunqian.common.codec;
import space.sunqian.annotations.Nonnull;
import space.sunqian.common.io.ByteProcessor;
import space.sunqian.common.io.ByteTransformer;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import java.nio.ByteBuffer;
/**
* Utilities for crypto.
*
* @author sunqian
*/
public class CryptoKit {
/**
* Returns a new {@link ByteTransformer} instance for the specified {@link Cipher}. The transformer uses
* {@link Cipher#doFinal(ByteBuffer, ByteBuffer)} to process the input data, and the input data is considered as a
* block that needs to be encoded/decoded.
* <p>
* If the cipher requires a specified input length, try using {@link ByteProcessor#readBlockSize(int)} or
* {@link ByteTransformer#withFixedSize(ByteTransformer, int)} to configure it.
*
* @param cipher the specified {@link Cipher}, should be initialized
* @return a new {@link ByteTransformer} instance for the specified {@link Cipher}
*/
public static @Nonnull ByteTransformer cipherTransformer(@Nonnull Cipher cipher) {
return new ByteTransformer() {
@Override
public @Nonnull ByteBuffer transform(@Nonnull ByteBuffer data, boolean end) throws Exception {
int outputSize = cipher.getOutputSize(data.remaining());
ByteBuffer out = ByteBuffer.allocate(outputSize);
cipher.doFinal(data, out);
out.flip();
return out;
}
};
}
/**
* Returns a new {@link ByteTransformer} instance for the specified {@link Mac}. The transformer uses
* {@link Mac#update(ByteBuffer)} and {@link Mac#doFinal()} to process the input data, and before the {@code end} is
* {@code true}, the transformer returns {@code null}.
* <p>
* If the digest requires a specified input length, try using {@link ByteProcessor#readBlockSize(int)} or
* {@link ByteTransformer#withFixedSize(ByteTransformer, int)} to configure it.
*
* @param mac the specified {@link Mac}, should be initialized
* @return a new {@link ByteTransformer} instance for the specified {@link Mac}
*/
public static @Nonnull ByteTransformer macTransformer(@Nonnull Mac mac) {
return (data, end) -> {
mac.update(data);
if (end) {
return ByteBuffer.wrap(mac.doFinal());
} else {
return null;
}
};
}
private CryptoKit() {
}
}