blob: 84a32cde63e17c1dc2c01bd6f646a886eb1a986c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
* file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.apache.tuweni.crypto.sodium;
import org.apache.tuweni.bytes.Bytes;
import java.util.Objects;
import javax.security.auth.Destroyable;
import jnr.ffi.Pointer;
/**
* Generic hashing utility (BLAKE2b).
*
* @see <a href="https://libsodium.gitbook.io/doc/hashing/generic_hashing">Generic hashing</a>
*
*/
public final class GenericHash {
/**
* Input of generic hash function.
*/
public static final class Input implements Destroyable {
private final Allocated value;
private Input(Pointer ptr, int length) {
this.value = new Allocated(ptr, length);
}
@Override
public void destroy() {
value.destroy();
}
@Override
public boolean isDestroyed() {
return value.isDestroyed();
}
/**
*
* @return the length of the input
*/
public int length() {
return value.length();
}
/**
* Create a {@link GenericHash.Input} from a pointer.
*
* @param allocated the allocated pointer
* @return An input.
*/
public static Input fromPointer(Allocated allocated) {
return new Input(Sodium.dup(allocated.pointer(), allocated.length()), allocated.length());
}
/**
* Create a {@link GenericHash.Input} from a hash.
*
* @param hash the hash
* @return An input.
*/
public static Input fromHash(Hash hash) {
return new Input(Sodium.dup(hash.value.pointer(), hash.value.length()), hash.value.length());
}
/**
* Create a {@link GenericHash.Input} from an array of bytes.
*
* @param bytes The bytes for the input.
* @return An input.
*/
public static Input fromBytes(Bytes bytes) {
return fromBytes(bytes.toArrayUnsafe());
}
/**
* Create a {@link GenericHash.Input} from an array of bytes.
*
* @param bytes The bytes for the input.
* @return An input.
*/
public static Input fromBytes(byte[] bytes) {
return Sodium.dup(bytes, GenericHash.Input::new);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof GenericHash.Input)) {
return false;
}
Input other = (Input) obj;
return other.value.equals(value);
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* @return The bytes of this key.
*/
public Bytes bytes() {
return value.bytes();
}
/**
* @return The bytes of this key.
*/
public byte[] bytesArray() {
return value.bytesArray();
}
}
/**
* Key of generic hash function.
*/
public static final class Key implements Destroyable {
private final Allocated value;
private Key(Pointer ptr, int length) {
this.value = new Allocated(ptr, length);
}
@Override
public void destroy() {
value.destroy();
}
@Override
public boolean isDestroyed() {
return value.isDestroyed();
}
/**
*
* @return the length of the key
*/
public int length() {
return value.length();
}
/**
* Create a {@link GenericHash.Key} from a pointer.
*
* @param allocated the allocated pointer
* @return A key.
*/
public static Key fromPointer(Allocated allocated) {
return new Key(Sodium.dup(allocated.pointer(), allocated.length()), allocated.length());
}
/**
* Create a {@link GenericHash.Key} from a hash.
*
* @param hash the hash
* @return A key.
*/
public static Key fromHash(Hash hash) {
return new Key(Sodium.dup(hash.value.pointer(), hash.value.length()), hash.value.length());
}
/**
* Create a {@link GenericHash.Key} from an array of bytes.
*
* @param bytes The bytes for the key.
* @return A key.
*/
public static Key fromBytes(Bytes bytes) {
return fromBytes(bytes.toArrayUnsafe());
}
/**
* Create a {@link GenericHash.Key} from an array of bytes.
*
* @param bytes The bytes for the key.
* @return A key.
*/
public static Key fromBytes(byte[] bytes) {
return Sodium.dup(bytes, GenericHash.Key::new);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof GenericHash.Key)) {
return false;
}
Key other = (Key) obj;
return other.value.equals(value);
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* @return The bytes of this key.
*/
public Bytes bytes() {
return value.bytes();
}
/**
* @return The bytes of this key.
*/
public byte[] bytesArray() {
return value.bytesArray();
}
}
/**
* Generic hash function output.
*/
public static final class Hash implements Destroyable {
Allocated value;
Hash(Pointer ptr, int length) {
this.value = new Allocated(ptr, length);
}
@Override
public void destroy() {
value.destroy();
}
@Override
public boolean isDestroyed() {
return value.isDestroyed();
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof GenericHash.Hash)) {
return false;
}
GenericHash.Hash other = (GenericHash.Hash) obj;
return other.value.equals(value);
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
/**
* Obtain the bytes of this hash.
*
* WARNING: This will cause the hash to be copied into heap memory.
*
* @return The bytes of this hash.
*/
public Bytes bytes() {
return value.bytes();
}
/**
* Obtain the bytes of this hash.
*
* WARNING: This will cause the hash to be copied into heap memory. The returned array should be overwritten when no
* longer required.
*
* @return The bytes of this hash.
*/
public byte[] bytesArray() {
return value.bytesArray();
}
/**
* Provide the length of this hash.
*
* @return the length of this hash.
*/
public int length() {
return value.length();
}
}
/**
* Creates a generic hash of specified length of the input
*
* @param hashLength the length of the hash
* @param input the input of the hash function
* @return the hash of the input
*/
public static Hash hash(int hashLength, Input input) {
Pointer output = Sodium.malloc(hashLength);
Sodium.crypto_generichash(output, hashLength, input.value.pointer(), input.length(), null, 0);
return new Hash(output, hashLength);
}
/**
* Creates a generic hash of specified length of the input
*
* @param hashLength the length of the hash
* @param input the input of the hash function
* @param key the key of the hash function
* @return the hash of the input
*/
public static Hash hash(int hashLength, Input input, Key key) {
Pointer output = Sodium.malloc(hashLength);
Sodium.crypto_generichash(
output,
hashLength,
input.value.pointer(),
input.length(),
key.value.pointer(),
key.length());
return new Hash(output, hashLength);
}
}