1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.prf; 18 19 import com.google.crypto.tink.AccessesPartialKey; 20 import com.google.crypto.tink.Key; 21 import com.google.crypto.tink.util.SecretBytes; 22 import com.google.errorprone.annotations.CanIgnoreReturnValue; 23 import com.google.errorprone.annotations.Immutable; 24 import com.google.errorprone.annotations.RestrictedApi; 25 import java.security.GeneralSecurityException; 26 import javax.annotation.Nullable; 27 28 /** 29 * Represents a key computing HKDF PRF. 30 * 31 * <p>HKDF PRF is specified in RFC 5869. 32 */ 33 @Immutable 34 public final class HkdfPrfKey extends PrfKey { 35 private final HkdfPrfParameters parameters; 36 private final SecretBytes keyBytes; 37 38 /** Builder for HkdfPrfKey. */ 39 public static final class Builder { 40 @Nullable private HkdfPrfParameters parameters = null; 41 @Nullable private SecretBytes keyBytes = null; 42 Builder()43 private Builder() {} 44 45 @CanIgnoreReturnValue setParameters(HkdfPrfParameters parameters)46 public Builder setParameters(HkdfPrfParameters parameters) { 47 this.parameters = parameters; 48 return this; 49 } 50 51 @CanIgnoreReturnValue setKeyBytes(SecretBytes keyBytes)52 public Builder setKeyBytes(SecretBytes keyBytes) { 53 this.keyBytes = keyBytes; 54 return this; 55 } 56 build()57 public HkdfPrfKey build() throws GeneralSecurityException { 58 if (parameters == null || keyBytes == null) { 59 throw new GeneralSecurityException("Cannot build without parameters and/or key material"); 60 } 61 62 if (parameters.getKeySizeBytes() != keyBytes.size()) { 63 throw new GeneralSecurityException("Key size mismatch"); 64 } 65 66 return new HkdfPrfKey(parameters, keyBytes); 67 } 68 } 69 HkdfPrfKey(HkdfPrfParameters parameters, SecretBytes keyBytes)70 private HkdfPrfKey(HkdfPrfParameters parameters, SecretBytes keyBytes) { 71 this.parameters = parameters; 72 this.keyBytes = keyBytes; 73 } 74 75 @RestrictedApi( 76 explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", 77 link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", 78 allowedOnPath = ".*Test\\.java", 79 allowlistAnnotations = {AccessesPartialKey.class}) builder()80 public static Builder builder() { 81 return new Builder(); 82 } 83 84 @RestrictedApi( 85 explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", 86 link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", 87 allowedOnPath = ".*Test\\.java", 88 allowlistAnnotations = {AccessesPartialKey.class}) getKeyBytes()89 public SecretBytes getKeyBytes() { 90 return keyBytes; 91 } 92 93 @Override getParameters()94 public HkdfPrfParameters getParameters() { 95 return parameters; 96 } 97 98 @Override 99 @Nullable getIdRequirementOrNull()100 public Integer getIdRequirementOrNull() { 101 return null; 102 } 103 104 @Override equalsKey(Key o)105 public boolean equalsKey(Key o) { 106 if (!(o instanceof HkdfPrfKey)) { 107 return false; 108 } 109 HkdfPrfKey that = (HkdfPrfKey) o; 110 return that.parameters.equals(parameters) && that.keyBytes.equalsSecretBytes(keyBytes); 111 } 112 } 113