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

com.google.crypto.tink.hybrid.EciesParameters Maven / Gradle / Ivy

// Copyright 2023 Google LLC
//
// Licensed 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 com.google.crypto.tink.hybrid;

import static com.google.crypto.tink.internal.TinkBugException.exceptionIsBug;

import com.google.crypto.tink.Parameters;
import com.google.crypto.tink.aead.AesCtrHmacAeadParameters;
import com.google.crypto.tink.aead.AesGcmParameters;
import com.google.crypto.tink.aead.XChaCha20Poly1305Parameters;
import com.google.crypto.tink.daead.AesSivParameters;
import com.google.crypto.tink.util.Bytes;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.Immutable;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * Parameters for an ECIES primitive with HKDF and AEAD encryption.
 *
 * 

This API follows loosely ECIES ISO 18033-2 standard (Elliptic Curve Integrated Encryption * Scheme, see http://www.shoup.net/iso/std6.pdf), but with some differences: * *

    *
  • use of HKDF key derivation function (instead of KDF1 and KDF2) enabling the use of optional * parameters to the key derivation function, which strenghten the overall security and allow * for binding the key material to application-specific information (see RFC 5869) *
  • use of modern AEAD/Deterministic AEAD schemes rather than "manual composition" of symmetric * encryption with message authentication codes (as in DEM1, DEM2, and DEM3 schemes of ISO * 18033-2) *
*/ public final class EciesParameters extends HybridParameters { private static Set listAcceptedDemParameters() throws GeneralSecurityException { HashSet acceptedDemParameters = new HashSet<>(); // AES128_GCM_RAW acceptedDemParameters.add( AesGcmParameters.builder() .setIvSizeBytes(12) .setKeySizeBytes(16) .setTagSizeBytes(16) .setVariant(AesGcmParameters.Variant.NO_PREFIX) .build()); // AES256_GCM_RAW acceptedDemParameters.add( AesGcmParameters.builder() .setIvSizeBytes(12) .setKeySizeBytes(32) .setTagSizeBytes(16) .setVariant(AesGcmParameters.Variant.NO_PREFIX) .build()); // AES128_CTR_HMAC_SHA256_RAW acceptedDemParameters.add( AesCtrHmacAeadParameters.builder() .setAesKeySizeBytes(16) .setHmacKeySizeBytes(32) .setTagSizeBytes(16) .setIvSizeBytes(16) .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) .build()); // AES256_CTR_HMAC_SHA256_RAW acceptedDemParameters.add( AesCtrHmacAeadParameters.builder() .setAesKeySizeBytes(32) .setHmacKeySizeBytes(32) .setTagSizeBytes(32) .setIvSizeBytes(16) .setHashType(AesCtrHmacAeadParameters.HashType.SHA256) .setVariant(AesCtrHmacAeadParameters.Variant.NO_PREFIX) .build()); // XCHACHA20_POLY1305_RAW acceptedDemParameters.add(XChaCha20Poly1305Parameters.create()); // AES256_SIV_RAW acceptedDemParameters.add( AesSivParameters.builder() .setKeySizeBytes(64) .setVariant(AesSivParameters.Variant.NO_PREFIX) .build()); return Collections.unmodifiableSet(acceptedDemParameters); } private static final Set acceptedDemParameters = exceptionIsBug(() -> listAcceptedDemParameters()); /** Description of the output prefix prepended to the ciphertext. */ @Immutable public static final class Variant { /** Leading 0x01-byte followed by 4-byte key id (big endian format). */ public static final Variant TINK = new Variant("TINK"); /** Leading 0x00-byte followed by 4-byte key id (big endian format). */ public static final Variant CRUNCHY = new Variant("CRUNCHY"); /** Empty prefix. */ public static final Variant NO_PREFIX = new Variant("NO_PREFIX"); private final String name; private Variant(String name) { this.name = name; } @Override public String toString() { return name; } } /** The elliptic curve type used for the KEM. */ @Immutable public static final class CurveType { public static final CurveType NIST_P256 = new CurveType("NIST_P256"); public static final CurveType NIST_P384 = new CurveType("NIST_P384"); public static final CurveType NIST_P521 = new CurveType("NIST_P521"); public static final CurveType X25519 = new CurveType("X25519"); private final String name; private CurveType(String name) { this.name = name; } @Override public String toString() { return name; } } /** The Hash algorithm used for the KEM. */ @Immutable public static final class HashType { public static final HashType SHA1 = new HashType("SHA1"); public static final HashType SHA224 = new HashType("SHA224"); public static final HashType SHA256 = new HashType("SHA256"); public static final HashType SHA384 = new HashType("SHA384"); public static final HashType SHA512 = new HashType("SHA512"); private final String name; private HashType(String name) { this.name = name; } @Override public String toString() { return name; } } /** The Elliptic Curve Point Format. */ @Immutable public static final class PointFormat { public static final PointFormat COMPRESSED = new PointFormat("COMPRESSED"); public static final PointFormat UNCOMPRESSED = new PointFormat("UNCOMPRESSED"); /** * Like {@code UNCOMPRESSED}, but without the \x04 prefix. Crunchy uses this format. DO NOT USE * unless you are a Crunchy user moving to Tink. */ public static final PointFormat LEGACY_UNCOMPRESSED = new PointFormat("LEGACY_UNCOMPRESSED"); private final String name; private PointFormat(String name) { this.name = name; } @Override public String toString() { return name; } } /** Builds a new {@link EciesParameters} instance. */ public static final class Builder { private CurveType curveType = null; private HashType hashType = null; private PointFormat nistCurvePointFormat = null; private Parameters demParameters = null; private Variant variant = Variant.NO_PREFIX; @Nullable private Bytes salt = null; private Builder() {} @CanIgnoreReturnValue public Builder setCurveType(CurveType curveType) { this.curveType = curveType; return this; } @CanIgnoreReturnValue public Builder setHashType(HashType hashType) { this.hashType = hashType; return this; } @CanIgnoreReturnValue public Builder setNistCurvePointFormat(PointFormat pointFormat) { this.nistCurvePointFormat = pointFormat; return this; } /** * Current implementation only accepts certain NO_PREFIX instances of AesGcmParameters, * AesCtrHmacAeadParameters, XChaCha20Poly1305Parameters or AesSivParameters. */ @CanIgnoreReturnValue public Builder setDemParameters(Parameters demParameters) throws GeneralSecurityException { if (!acceptedDemParameters.contains(demParameters)) { throw new GeneralSecurityException( "Invalid DEM parameters " + demParameters + "; only AES128_GCM_RAW, AES256_GCM_RAW, AES128_CTR_HMAC_SHA256_RAW," + " AES256_CTR_HMAC_SHA256_RAW XCHACHA20_POLY1305_RAW and AES256_SIV_RAW are" + " currently supported."); } this.demParameters = demParameters; return this; } @CanIgnoreReturnValue public Builder setVariant(Variant variant) { this.variant = variant; return this; } /** Defaults to null if not set. */ @CanIgnoreReturnValue public Builder setSalt(Bytes salt) { if (salt.size() == 0) { this.salt = null; return this; } this.salt = salt; return this; } public EciesParameters build() throws GeneralSecurityException { if (curveType == null) { throw new GeneralSecurityException("Elliptic curve type is not set"); } if (hashType == null) { throw new GeneralSecurityException("Hash type is not set"); } if (demParameters == null) { throw new GeneralSecurityException("DEM parameters are not set"); } if (variant == null) { throw new GeneralSecurityException("Variant is not set"); } if (curveType != CurveType.X25519 && nistCurvePointFormat == null) { throw new GeneralSecurityException("Point format is not set"); } if (curveType == CurveType.X25519 && nistCurvePointFormat != null) { throw new GeneralSecurityException("For Curve25519 point format must not be set"); } return new EciesParameters( curveType, hashType, nistCurvePointFormat, demParameters, variant, salt); } } private final CurveType curveType; private final HashType hashType; @Nullable private final PointFormat nistCurvePointFormat; private final Variant variant; private final Parameters demParameters; @Nullable private final Bytes salt; private EciesParameters( CurveType curveType, HashType hashType, @Nullable PointFormat pointFormat, Parameters demParameters, Variant variant, Bytes salt) { this.curveType = curveType; this.hashType = hashType; this.nistCurvePointFormat = pointFormat; this.demParameters = demParameters; this.variant = variant; this.salt = salt; } public static Builder builder() { return new Builder(); } public CurveType getCurveType() { return curveType; } public HashType getHashType() { return hashType; } @Nullable public PointFormat getNistCurvePointFormat() { return nistCurvePointFormat; } public Parameters getDemParameters() { return demParameters; } public Variant getVariant() { return variant; } /** * Gets the salt value, which defaults to null if not set. * *

This class does not store an RFC compliant default value and the converion must be done in * the implementation (meaning that a null salt must be converted to a string of zeros that is of * the length of the hash function output, as per RFC 5869). */ @Nullable public Bytes getSalt() { return salt; } @Override public boolean hasIdRequirement() { return variant != Variant.NO_PREFIX; } @Override public boolean equals(Object o) { if (!(o instanceof EciesParameters)) { return false; } EciesParameters that = (EciesParameters) o; return Objects.equals(that.getCurveType(), getCurveType()) && Objects.equals(that.getHashType(), getHashType()) && Objects.equals(that.getNistCurvePointFormat(), getNistCurvePointFormat()) && Objects.equals(that.getDemParameters(), getDemParameters()) && Objects.equals(that.getVariant(), getVariant()) && Objects.equals(that.getSalt(), getSalt()); } @Override public int hashCode() { return Objects.hash( EciesParameters.class, curveType, hashType, nistCurvePointFormat, demParameters, variant, salt); } @Override public String toString() { return String.format( "EciesParameters(curveType=%s, hashType=%s, pointFormat=%s, demParameters=%s, variant=%s," + " salt=%s)", curveType, hashType, nistCurvePointFormat, demParameters, variant, salt); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy