• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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.subtle;
18 
19 import com.google.crypto.tink.AccessesPartialKey;
20 import com.google.crypto.tink.HybridEncrypt;
21 import com.google.crypto.tink.hybrid.EciesParameters;
22 import com.google.crypto.tink.hybrid.EciesPublicKey;
23 import com.google.crypto.tink.hybrid.internal.EciesDemHelper;
24 import com.google.crypto.tink.internal.EnumTypeProtoConverter;
25 import com.google.crypto.tink.subtle.EllipticCurves.PointFormatType;
26 import java.security.GeneralSecurityException;
27 import java.security.interfaces.ECPublicKey;
28 
29 /**
30  * ECIES encryption with HKDF-KEM (key encapsulation mechanism) and AEAD-DEM (data encapsulation
31  * mechanism).
32  *
33  * @since 1.0.0
34  */
35 public final class EciesAeadHkdfHybridEncrypt implements HybridEncrypt {
36   private final EciesHkdfSenderKem senderKem;
37   private final String hkdfHmacAlgo;
38   private final byte[] hkdfSalt;
39   private final EllipticCurves.PointFormatType ecPointFormat;
40   private final EciesDemHelper.Dem dem;
41   private final byte[] outputPrefix;
42 
toHmacAlgo(EciesParameters.HashType hash)43   static final String toHmacAlgo(EciesParameters.HashType hash) throws GeneralSecurityException {
44     if (hash.equals(EciesParameters.HashType.SHA1)) {
45       return "HmacSha1";
46     }
47     if (hash.equals(EciesParameters.HashType.SHA224)) {
48       return "HmacSha224";
49     }
50     if (hash.equals(EciesParameters.HashType.SHA256)) {
51       return "HmacSha256";
52     }
53     if (hash.equals(EciesParameters.HashType.SHA384)) {
54       return "HmacSha384";
55     }
56     if (hash.equals(EciesParameters.HashType.SHA512)) {
57       return "HmacSha512";
58     }
59     throw new GeneralSecurityException("hash unsupported for EciesAeadHkdf: " + hash);
60   }
61 
62   static final EnumTypeProtoConverter<EllipticCurves.CurveType, EciesParameters.CurveType>
63       CURVE_TYPE_CONVERTER =
64           EnumTypeProtoConverter.<EllipticCurves.CurveType, EciesParameters.CurveType>builder()
65               .add(EllipticCurves.CurveType.NIST_P256, EciesParameters.CurveType.NIST_P256)
66               .add(EllipticCurves.CurveType.NIST_P384, EciesParameters.CurveType.NIST_P384)
67               .add(EllipticCurves.CurveType.NIST_P521, EciesParameters.CurveType.NIST_P521)
68               .build();
69 
70   static final EnumTypeProtoConverter<EllipticCurves.PointFormatType, EciesParameters.PointFormat>
71       POINT_FORMAT_TYPE_CONVERTER =
72           EnumTypeProtoConverter
73               .<EllipticCurves.PointFormatType, EciesParameters.PointFormat>builder()
74               .add(PointFormatType.UNCOMPRESSED, EciesParameters.PointFormat.UNCOMPRESSED)
75               .add(PointFormatType.COMPRESSED, EciesParameters.PointFormat.COMPRESSED)
76               .add(
77                   PointFormatType.DO_NOT_USE_CRUNCHY_UNCOMPRESSED,
78                   EciesParameters.PointFormat.LEGACY_UNCOMPRESSED)
79               .build();
80 
EciesAeadHkdfHybridEncrypt( final ECPublicKey recipientPublicKey, final byte[] hkdfSalt, String hkdfHmacAlgo, EllipticCurves.PointFormatType ecPointFormat, EciesDemHelper.Dem dem, byte[] outputPrefix)81   private EciesAeadHkdfHybridEncrypt(
82       final ECPublicKey recipientPublicKey,
83       final byte[] hkdfSalt,
84       String hkdfHmacAlgo,
85       EllipticCurves.PointFormatType ecPointFormat,
86       EciesDemHelper.Dem dem,
87       byte[] outputPrefix)
88       throws GeneralSecurityException {
89     EllipticCurves.checkPublicKey(recipientPublicKey);
90     this.senderKem = new EciesHkdfSenderKem(recipientPublicKey);
91     this.hkdfSalt = hkdfSalt;
92     this.hkdfHmacAlgo = hkdfHmacAlgo;
93     this.ecPointFormat = ecPointFormat;
94     this.dem = dem;
95     this.outputPrefix = outputPrefix;
96   }
97 
98   @AccessesPartialKey
create(EciesPublicKey key)99   public static HybridEncrypt create(EciesPublicKey key) throws GeneralSecurityException {
100     EllipticCurves.CurveType curveType =
101         CURVE_TYPE_CONVERTER.toProtoEnum(key.getParameters().getCurveType());
102     ECPublicKey recipientPublicKey =
103         EllipticCurves.getEcPublicKey(
104             curveType,
105             key.getNistCurvePoint().getAffineX().toByteArray(),
106             key.getNistCurvePoint().getAffineY().toByteArray());
107     byte[] hkdfSalt = new byte[0];
108     if (key.getParameters().getSalt() != null) {
109       hkdfSalt = key.getParameters().getSalt().toByteArray();
110     }
111     return new EciesAeadHkdfHybridEncrypt(
112         recipientPublicKey,
113         hkdfSalt,
114         toHmacAlgo(key.getParameters().getHashType()),
115         POINT_FORMAT_TYPE_CONVERTER.toProtoEnum(key.getParameters().getNistCurvePointFormat()),
116         EciesDemHelper.getDem(key.getParameters()),
117         key.getOutputPrefix().toByteArray());
118   }
119 
120   /**
121    * Encrypts {@code plaintext} using {@code contextInfo} as <b>info</b>-parameter of the underlying
122    * HKDF.
123    *
124    * @return resulting ciphertext.
125    */
126   @Override
encrypt(final byte[] plaintext, final byte[] contextInfo)127   public byte[] encrypt(final byte[] plaintext, final byte[] contextInfo)
128       throws GeneralSecurityException {
129     EciesHkdfSenderKem.KemKey kemKey =
130         senderKem.generateKey(
131             hkdfHmacAlgo, hkdfSalt, contextInfo, dem.getSymmetricKeySizeInBytes(), ecPointFormat);
132     return dem.encrypt(kemKey.getSymmetricKey(), outputPrefix, kemKey.getKemBytes(), plaintext);
133   }
134 }
135