• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.signature;
18 
19 import com.google.crypto.tink.AccessesPartialKey;
20 import com.google.crypto.tink.Key;
21 import com.google.crypto.tink.internal.OutputPrefixUtil;
22 import com.google.crypto.tink.util.Bytes;
23 import com.google.errorprone.annotations.Immutable;
24 import com.google.errorprone.annotations.RestrictedApi;
25 import java.security.GeneralSecurityException;
26 import java.util.Objects;
27 import javax.annotation.Nullable;
28 
29 /** Ed25519PublicKey represents the public portion of the Ed25519 signature primitive. */
30 @Immutable
31 public final class Ed25519PublicKey extends SignaturePublicKey {
32   private final Ed25519Parameters parameters;
33   private final Bytes publicKeyBytes;
34   private final Bytes outputPrefix;
35   @Nullable private final Integer idRequirement;
36 
Ed25519PublicKey( Ed25519Parameters parameters, Bytes publicKeyBytes, Bytes outputPrefix, @Nullable Integer idRequirement)37   private Ed25519PublicKey(
38       Ed25519Parameters parameters,
39       Bytes publicKeyBytes,
40       Bytes outputPrefix,
41       @Nullable Integer idRequirement) {
42     this.parameters = parameters;
43     this.publicKeyBytes = publicKeyBytes;
44     this.outputPrefix = outputPrefix;
45     this.idRequirement = idRequirement;
46   }
47 
createOutputPrefix( Ed25519Parameters parameters, @Nullable Integer idRequirement)48   private static Bytes createOutputPrefix(
49       Ed25519Parameters parameters, @Nullable Integer idRequirement) {
50     if (parameters.getVariant() == Ed25519Parameters.Variant.NO_PREFIX) {
51       return OutputPrefixUtil.EMPTY_PREFIX;
52     }
53     if (parameters.getVariant() == Ed25519Parameters.Variant.CRUNCHY
54         || parameters.getVariant() == Ed25519Parameters.Variant.LEGACY) {
55       return OutputPrefixUtil.getLegacyOutputPrefix(idRequirement);
56     }
57     if (parameters.getVariant() == Ed25519Parameters.Variant.TINK) {
58       return OutputPrefixUtil.getTinkOutputPrefix(idRequirement);
59     }
60     throw new IllegalStateException("Unknown Variant: " + parameters.getVariant());
61   }
62 
63   @Override
getOutputPrefix()64   public Bytes getOutputPrefix() {
65     return outputPrefix;
66   }
67 
68   @RestrictedApi(
69       explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey",
70       link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys",
71       allowedOnPath = ".*Test\\.java",
72       allowlistAnnotations = {AccessesPartialKey.class})
73   @AccessesPartialKey
create(Bytes publicKeyBytes)74   public static Ed25519PublicKey create(Bytes publicKeyBytes) throws GeneralSecurityException {
75     return create(Ed25519Parameters.Variant.NO_PREFIX, publicKeyBytes, null);
76   }
77 
78   @RestrictedApi(
79       explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey",
80       link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys",
81       allowedOnPath = ".*Test\\.java",
82       allowlistAnnotations = {AccessesPartialKey.class})
create( Ed25519Parameters.Variant variant, Bytes publicKeyBytes, @Nullable Integer idRequirement)83   public static Ed25519PublicKey create(
84       Ed25519Parameters.Variant variant, Bytes publicKeyBytes, @Nullable Integer idRequirement)
85       throws GeneralSecurityException {
86     Ed25519Parameters parameters = Ed25519Parameters.create(variant);
87     if (!variant.equals(Ed25519Parameters.Variant.NO_PREFIX) && idRequirement == null) {
88       throw new GeneralSecurityException(
89           "For given Variant " + variant + " the value of idRequirement must be non-null");
90       }
91 
92     if (variant.equals(Ed25519Parameters.Variant.NO_PREFIX) && idRequirement != null) {
93       throw new GeneralSecurityException(
94           "For given Variant NO_PREFIX the value of idRequirement must be null");
95     }
96     if (publicKeyBytes.size() != 32) {
97       throw new GeneralSecurityException(
98           "Ed25519 key must be constructed with key of length 32 bytes, not "
99               + publicKeyBytes.size());
100     }
101 
102     return new Ed25519PublicKey(
103         parameters, publicKeyBytes, createOutputPrefix(parameters, idRequirement), idRequirement);
104   }
105 
106   @RestrictedApi(
107       explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey",
108       link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys",
109       allowedOnPath = ".*Test\\.java",
110       allowlistAnnotations = {AccessesPartialKey.class})
getPublicKeyBytes()111   public Bytes getPublicKeyBytes() {
112     return publicKeyBytes;
113   }
114 
115   @Override
getParameters()116   public Ed25519Parameters getParameters() {
117     return parameters;
118   }
119 
120   @Override
121   @Nullable
getIdRequirementOrNull()122   public Integer getIdRequirementOrNull() {
123     return idRequirement;
124   }
125 
126   @Override
equalsKey(Key o)127   public boolean equalsKey(Key o) {
128     if (!(o instanceof Ed25519PublicKey)) {
129       return false;
130     }
131     Ed25519PublicKey that = (Ed25519PublicKey) o;
132     // Since outputPrefix is a function of parameters, we can ignore it here.
133     return that.parameters.equals(parameters)
134         && that.publicKeyBytes.equals(publicKeyBytes)
135         && Objects.equals(that.idRequirement, idRequirement);
136   }
137 }
138