-
Notifications
You must be signed in to change notification settings - Fork 122
/
Copy pathMasterKey.java
132 lines (118 loc) · 4.53 KB
/
MasterKey.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except
* in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.amazonaws.encryptionsdk;
import com.amazonaws.encryptionsdk.exception.NoSuchMasterKeyException;
import com.amazonaws.encryptionsdk.exception.UnsupportedProviderException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Represents the cryptographic key used to protect the {@link DataKey} (which, in turn, protects
* the data).
*
* <p>All MasterKeys extend {@link MasterKeyProvider} because they are all capable of providing
* exactly themselves. This simplifies implementation when only a single {@link MasterKey} is used
* and/or expected.
*
* @param <K> the concrete type of the {@link MasterKey}
*/
public abstract class MasterKey<K extends MasterKey<K>> extends MasterKeyProvider<K> {
public abstract String getProviderId();
/** Equivalent to calling {@link #getProviderId()}. */
@Override
public String getDefaultProviderId() {
return getProviderId();
}
public abstract String getKeyId();
/**
* Generates a new {@link DataKey} which is protected by this {@link MasterKey} for use with
* {@code algorithm} and associated with the provided {@code encryptionContext}.
*/
public abstract DataKey<K> generateDataKey(
CryptoAlgorithm algorithm, Map<String, String> encryptionContext);
/**
* Returns a new copy of the provided {@code dataKey} which is protected by this {@link MasterKey}
* for use with {@code algorithm} and associated with the provided {@code encryptionContext}.
*/
public abstract DataKey<K> encryptDataKey(
CryptoAlgorithm algorithm, Map<String, String> encryptionContext, DataKey<?> dataKey);
/** Returns {@code true} if and only if {@code provider} equals {@link #getProviderId()}. */
@Override
public boolean canProvide(final String provider) {
return getProviderId().equals(provider);
}
/**
* Returns {@code this} if {@code provider} and {@code keyId} match {@code this}. Otherwise,
* throws an appropriate exception.
*/
@SuppressWarnings("unchecked")
@Override
public K getMasterKey(final String provider, final String keyId)
throws UnsupportedProviderException, NoSuchMasterKeyException {
if (!canProvide(provider)) {
throw new UnsupportedProviderException(
"MasterKeys can only provide themselves. Requested "
+ buildName(provider, keyId)
+ " but only "
+ toString()
+ " is available");
}
if (!getKeyId().equals(keyId)) {
throw new NoSuchMasterKeyException(
"MasterKeys can only provide themselves. Requested "
+ buildName(provider, keyId)
+ " but only "
+ toString()
+ " is available");
}
return (K) this;
}
@Override
public String toString() {
return buildName(getProviderId(), getKeyId());
}
/** Returns a list of length {@code 1} containing {@code this}. */
@SuppressWarnings("unchecked")
@Override
public List<K> getMasterKeysForEncryption(final MasterKeyRequest request) {
return (List<K>) Collections.singletonList(this);
}
private static String buildName(final String provider, final String keyId) {
return String.format("%s://%s", provider, keyId);
}
/**
* Two {@link MasterKey}s are equal if they are instances of the <em>exact same class</em> and
* their values for {@code keyId}, {@code providerId}, and {@code defaultProviderId} are equal.
*/
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (!obj.getClass().equals(getClass())) {
return false;
}
final MasterKey<?> mk = (MasterKey<?>) obj;
return Objects.equals(getKeyId(), mk.getKeyId())
&& Objects.equals(getProviderId(), mk.getProviderId())
&& Objects.equals(getDefaultProviderId(), mk.getDefaultProviderId());
}
@Override
public int hashCode() {
return Objects.hash(getKeyId(), getProviderId(), getDefaultProviderId());
}
}