HBASE-10065. Stronger validation of key unwrapping
git-svn-id: https://svn.apache.org/repos/asf/hbase/trunk@1547374 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c525383e8d
commit
969a276679
|
@ -23,7 +23,6 @@ import java.io.IOException;
|
|||
import java.security.Key;
|
||||
import java.security.KeyException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
|
@ -34,6 +33,7 @@ import org.apache.hadoop.hbase.HConstants;
|
|||
import org.apache.hadoop.hbase.io.crypto.Cipher;
|
||||
import org.apache.hadoop.hbase.io.crypto.Encryption;
|
||||
import org.apache.hadoop.hbase.protobuf.generated.EncryptionProtos;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
|
||||
import com.google.protobuf.ZeroCopyLiteralByteString;
|
||||
|
||||
|
@ -87,17 +87,16 @@ public class EncryptionUtil {
|
|||
builder.setIv(ZeroCopyLiteralByteString.wrap(iv));
|
||||
}
|
||||
byte[] keyBytes = key.getEncoded();
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(keyBytes);
|
||||
builder.setLength(keyBytes.length);
|
||||
builder.setHash(ZeroCopyLiteralByteString.wrap(Encryption.hash128(keyBytes)));
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Encryption.encryptWithSubjectKey(out, new ByteArrayInputStream(keyBytes), subject,
|
||||
conf, cipher, iv);
|
||||
builder.setData(ZeroCopyLiteralByteString.wrap(out.toByteArray()));
|
||||
builder.setCrc((int)crc.getValue());
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
builder.build().writeDelimitedTo(os);
|
||||
return os.toByteArray();
|
||||
// Build and return the protobuf message
|
||||
out.reset();
|
||||
builder.build().writeDelimitedTo(out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,11 +123,9 @@ public class EncryptionUtil {
|
|||
Encryption.decryptWithSubjectKey(out, wrappedKey.getData().newInput(),
|
||||
wrappedKey.getLength(), subject, conf, cipher, iv);
|
||||
byte[] keyBytes = out.toByteArray();
|
||||
if (wrappedKey.hasCrc()) {
|
||||
CRC32 crc = new CRC32();
|
||||
crc.update(keyBytes);
|
||||
if ((int)(crc.getValue()&0xffffffff) != wrappedKey.getCrc()) {
|
||||
throw new KeyException("Key was not successfully unwrapped: CRC check failed");
|
||||
if (wrappedKey.hasHash()) {
|
||||
if (!Bytes.equals(wrappedKey.getHash().toByteArray(), Encryption.hash128(keyBytes))) {
|
||||
throw new KeyException("Key was not successfully unwrapped");
|
||||
}
|
||||
}
|
||||
return new SecretKeySpec(keyBytes, wrappedKey.getAlgorithm());
|
||||
|
|
|
@ -56,15 +56,15 @@ public final class EncryptionProtos {
|
|||
*/
|
||||
com.google.protobuf.ByteString getIv();
|
||||
|
||||
// optional fixed32 crc = 5;
|
||||
// optional bytes hash = 5;
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
boolean hasCrc();
|
||||
boolean hasHash();
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
int getCrc();
|
||||
com.google.protobuf.ByteString getHash();
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code WrappedKey}
|
||||
|
@ -137,9 +137,9 @@ public final class EncryptionProtos {
|
|||
iv_ = input.readBytes();
|
||||
break;
|
||||
}
|
||||
case 45: {
|
||||
case 42: {
|
||||
bitField0_ |= 0x00000010;
|
||||
crc_ = input.readFixed32();
|
||||
hash_ = input.readBytes();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -273,20 +273,20 @@ public final class EncryptionProtos {
|
|||
return iv_;
|
||||
}
|
||||
|
||||
// optional fixed32 crc = 5;
|
||||
public static final int CRC_FIELD_NUMBER = 5;
|
||||
private int crc_;
|
||||
// optional bytes hash = 5;
|
||||
public static final int HASH_FIELD_NUMBER = 5;
|
||||
private com.google.protobuf.ByteString hash_;
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public boolean hasCrc() {
|
||||
public boolean hasHash() {
|
||||
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||
}
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public int getCrc() {
|
||||
return crc_;
|
||||
public com.google.protobuf.ByteString getHash() {
|
||||
return hash_;
|
||||
}
|
||||
|
||||
private void initFields() {
|
||||
|
@ -294,7 +294,7 @@ public final class EncryptionProtos {
|
|||
length_ = 0;
|
||||
data_ = com.google.protobuf.ByteString.EMPTY;
|
||||
iv_ = com.google.protobuf.ByteString.EMPTY;
|
||||
crc_ = 0;
|
||||
hash_ = com.google.protobuf.ByteString.EMPTY;
|
||||
}
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
|
@ -333,7 +333,7 @@ public final class EncryptionProtos {
|
|||
output.writeBytes(4, iv_);
|
||||
}
|
||||
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||
output.writeFixed32(5, crc_);
|
||||
output.writeBytes(5, hash_);
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ public final class EncryptionProtos {
|
|||
}
|
||||
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||
size += com.google.protobuf.CodedOutputStream
|
||||
.computeFixed32Size(5, crc_);
|
||||
.computeBytesSize(5, hash_);
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSerializedSize = size;
|
||||
|
@ -407,10 +407,10 @@ public final class EncryptionProtos {
|
|||
result = result && getIv()
|
||||
.equals(other.getIv());
|
||||
}
|
||||
result = result && (hasCrc() == other.hasCrc());
|
||||
if (hasCrc()) {
|
||||
result = result && (getCrc()
|
||||
== other.getCrc());
|
||||
result = result && (hasHash() == other.hasHash());
|
||||
if (hasHash()) {
|
||||
result = result && getHash()
|
||||
.equals(other.getHash());
|
||||
}
|
||||
result = result &&
|
||||
getUnknownFields().equals(other.getUnknownFields());
|
||||
|
@ -441,9 +441,9 @@ public final class EncryptionProtos {
|
|||
hash = (37 * hash) + IV_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getIv().hashCode();
|
||||
}
|
||||
if (hasCrc()) {
|
||||
hash = (37 * hash) + CRC_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getCrc();
|
||||
if (hasHash()) {
|
||||
hash = (37 * hash) + HASH_FIELD_NUMBER;
|
||||
hash = (53 * hash) + getHash().hashCode();
|
||||
}
|
||||
hash = (29 * hash) + getUnknownFields().hashCode();
|
||||
memoizedHashCode = hash;
|
||||
|
@ -562,7 +562,7 @@ public final class EncryptionProtos {
|
|||
bitField0_ = (bitField0_ & ~0x00000004);
|
||||
iv_ = com.google.protobuf.ByteString.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000008);
|
||||
crc_ = 0;
|
||||
hash_ = com.google.protobuf.ByteString.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000010);
|
||||
return this;
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ public final class EncryptionProtos {
|
|||
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
|
||||
to_bitField0_ |= 0x00000010;
|
||||
}
|
||||
result.crc_ = crc_;
|
||||
result.hash_ = hash_;
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
|
@ -642,8 +642,8 @@ public final class EncryptionProtos {
|
|||
if (other.hasIv()) {
|
||||
setIv(other.getIv());
|
||||
}
|
||||
if (other.hasCrc()) {
|
||||
setCrc(other.getCrc());
|
||||
if (other.hasHash()) {
|
||||
setHash(other.getHash());
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
|
@ -863,35 +863,38 @@ public final class EncryptionProtos {
|
|||
return this;
|
||||
}
|
||||
|
||||
// optional fixed32 crc = 5;
|
||||
private int crc_ ;
|
||||
// optional bytes hash = 5;
|
||||
private com.google.protobuf.ByteString hash_ = com.google.protobuf.ByteString.EMPTY;
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public boolean hasCrc() {
|
||||
public boolean hasHash() {
|
||||
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||
}
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public int getCrc() {
|
||||
return crc_;
|
||||
public com.google.protobuf.ByteString getHash() {
|
||||
return hash_;
|
||||
}
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public Builder setCrc(int value) {
|
||||
bitField0_ |= 0x00000010;
|
||||
crc_ = value;
|
||||
public Builder setHash(com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
bitField0_ |= 0x00000010;
|
||||
hash_ = value;
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>optional fixed32 crc = 5;</code>
|
||||
* <code>optional bytes hash = 5;</code>
|
||||
*/
|
||||
public Builder clearCrc() {
|
||||
public Builder clearHash() {
|
||||
bitField0_ = (bitField0_ & ~0x00000010);
|
||||
crc_ = 0;
|
||||
hash_ = getDefaultInstance().getHash();
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
@ -921,11 +924,11 @@ public final class EncryptionProtos {
|
|||
descriptor;
|
||||
static {
|
||||
java.lang.String[] descriptorData = {
|
||||
"\n\020Encryption.proto\"V\n\nWrappedKey\022\021\n\talgo" +
|
||||
"\n\020Encryption.proto\"W\n\nWrappedKey\022\021\n\talgo" +
|
||||
"rithm\030\001 \002(\t\022\016\n\006length\030\002 \002(\r\022\014\n\004data\030\003 \002(" +
|
||||
"\014\022\n\n\002iv\030\004 \001(\014\022\013\n\003crc\030\005 \001(\007BC\n*org.apache" +
|
||||
".hadoop.hbase.protobuf.generatedB\020Encryp" +
|
||||
"tionProtosH\001\240\001\001"
|
||||
"\014\022\n\n\002iv\030\004 \001(\014\022\014\n\004hash\030\005 \001(\014BC\n*org.apach" +
|
||||
"e.hadoop.hbase.protobuf.generatedB\020Encry" +
|
||||
"ptionProtosH\001\240\001\001"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||
|
@ -937,7 +940,7 @@ public final class EncryptionProtos {
|
|||
internal_static_WrappedKey_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_WrappedKey_descriptor,
|
||||
new java.lang.String[] { "Algorithm", "Length", "Data", "Iv", "Crc", });
|
||||
new java.lang.String[] { "Algorithm", "Length", "Data", "Iv", "Hash", });
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -28,5 +28,5 @@ message WrappedKey {
|
|||
required uint32 length = 2;
|
||||
required bytes data = 3;
|
||||
optional bytes iv = 4;
|
||||
optional fixed32 crc = 5;
|
||||
optional bytes hash = 5;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue