use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class COSCryptoModuleBase method buildContentCryptoMaterial.
/**
* @param materials a non-null encryption material
*/
private ContentCryptoMaterial buildContentCryptoMaterial(EncryptionMaterials materials, Provider provider, CosServiceRequest req) {
byte[] iv = contentCryptoScheme.getIV();
if (iv == null) {
// Randomly generate the IV
iv = new byte[contentCryptoScheme.getIVLengthInBytes()];
cryptoScheme.getSecureRandom().nextBytes(iv);
}
if (materials.isKMSEnabled()) {
final Map<String, String> encryptionContext = ContentCryptoMaterial.mergeMaterialDescriptions(materials, req);
GenerateDataKeyRequest keyGenReq = new GenerateDataKeyRequest();
try {
ObjectMapper mapper = new ObjectMapper();
keyGenReq.setEncryptionContext(mapper.writeValueAsString(encryptionContext));
} catch (JsonProcessingException e) {
throw new CosClientException("generate datakey request set encryption context got json processing exception", e);
}
keyGenReq.setKeyId(materials.getCustomerMasterKeyId());
keyGenReq.setKeySpec(contentCryptoScheme.getKeySpec());
GenerateDataKeyResponse keyGenRes = kms.generateDataKey(keyGenReq);
byte[] key = Base64.decode(keyGenRes.getPlaintext());
final SecretKey cek = new SecretKeySpec(key, contentCryptoScheme.getKeyGeneratorAlgorithm());
byte[] keyBlob = keyGenRes.getCiphertextBlob().getBytes();
byte[] securedIV = ContentCryptoMaterial.encryptIV(iv, materials, cryptoScheme.getKeyWrapScheme(), cryptoScheme.getSecureRandom(), provider, kms, req);
return ContentCryptoMaterial.wrap(cek, iv, contentCryptoScheme, provider, new KMSSecuredCEK(keyBlob, encryptionContext), securedIV);
} else {
// Generate a one-time use symmetric key and initialize a cipher to encrypt object data
return ContentCryptoMaterial.create(generateCEK(materials, provider), iv, materials, cryptoScheme, provider, kms, req);
}
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class COSCryptoModuleBase method newCOSCipherLiteInputStream.
private CipherLiteInputStream newCOSCipherLiteInputStream(AbstractPutObjectRequest req, ContentCryptoMaterial cekMaterial, long plaintextLength) {
final File fileOrig = req.getFile();
final InputStream isOrig = req.getInputStream();
InputStream isCurr = null;
try {
if (fileOrig == null) {
// When input is a FileInputStream, this wrapping enables
// unlimited mark-and-reset
isCurr = isOrig == null ? null : ReleasableInputStream.wrap(isOrig);
} else {
isCurr = new ResettableInputStream(fileOrig);
}
if (plaintextLength > -1) {
// COS allows a single PUT to be no more than 5GB, which
// therefore won't exceed the maximum length that can be
// encrypted either using any cipher such as CBC or GCM.
// This ensures the plain-text read from the underlying data
// stream has the same length as the expected total.
isCurr = new LengthCheckInputStream(isCurr, plaintextLength, EXCLUDE_SKIPPED_BYTES);
}
final CipherLite cipherLite = cekMaterial.getCipherLite();
if (cipherLite.markSupported()) {
return new CipherLiteInputStream(isCurr, cipherLite, DEFAULT_BUFFER_SIZE);
} else {
return new RenewableCipherLiteInputStream(isCurr, cipherLite, DEFAULT_BUFFER_SIZE);
}
} catch (Exception e) {
cleanupDataSource(req, fileOrig, isOrig, isCurr, log);
throw new CosClientException("Unable to create cipher input stream", e);
}
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class ContentCryptoMaterial method decryptIV.
public static byte[] decryptIV(byte[] iv, String keyWrapAlgo, EncryptionMaterials materials, Provider securityProvider, ContentCryptoScheme contentCryptoScheme, QCLOUDKMS kms) {
if (materials.isKMSEnabled()) {
DecryptRequest decryptReq = new DecryptRequest();
Map<String, String> materialDesc = materials.getMaterialsDescription();
try {
ObjectMapper mapper = new ObjectMapper();
decryptReq.setEncryptionContext(mapper.writeValueAsString(materialDesc));
} catch (JsonProcessingException e) {
throw new CosClientException("decrypt request set encryption context got json processing exception", e);
}
decryptReq.setCiphertextBlob(new String(iv, Charset.forName("UTF-8")));
DecryptResponse decryptRes = kms.decrypt(decryptReq);
return Base64.decode(decryptRes.getPlaintext());
}
Key kek;
if (materials.getKeyPair() != null) {
// Do envelope decryption with private key from key pair
kek = materials.getKeyPair().getPrivate();
if (kek == null) {
throw new CosClientException("Key encrypting key not available");
}
} else {
// Do envelope decryption with symmetric key
kek = materials.getSymmetricKey();
if (kek == null) {
throw new CosClientException("Key encrypting key not available");
}
}
try {
if (keyWrapAlgo != null) {
// Key wrapping specified
Cipher cipher = securityProvider == null ? Cipher.getInstance(keyWrapAlgo) : Cipher.getInstance(keyWrapAlgo, securityProvider);
cipher.init(Cipher.DECRYPT_MODE, kek);
return cipher.doFinal(iv);
}
// fall back to the Encryption Only (EO) key decrypting method
Cipher cipher;
if (securityProvider != null) {
cipher = Cipher.getInstance(kek.getAlgorithm(), securityProvider);
} else {
cipher = Cipher.getInstance(kek.getAlgorithm());
}
cipher.init(Cipher.DECRYPT_MODE, kek);
return cipher.doFinal(iv);
} catch (Exception e) {
throw new CosClientException("Unable to decrypt symmetric key from object metadata", e);
}
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class ContentCryptoMaterial method recreate.
/**
* Recreates a new content crypto material from the current material given a new KEK encryption
* materials. The purpose is to re-encrypt the CEK under the new KEK.
*
* Note network calls are involved if the CEK has been or is to be protected by KMS.
*
* @param newKEK encryption materials for the new KEK; must not be null
* @param accessor used to retrieve the original KEK given the corresponding material
* description
* @param targetScheme the target crypto scheme to use for recreating the content crypto
* material
* @param p optional security provider; null means to use the default.
* @throws SecurityException if the old and new material description are the same; or if the old
* and new KEK are the same
*/
ContentCryptoMaterial recreate(EncryptionMaterials newKEK, EncryptionMaterialsAccessor accessor, COSCryptoScheme targetScheme, Provider p, QCLOUDKMS kms, CosServiceRequest req) {
if (!usesKMSKey() && newKEK.getMaterialsDescription().equals(kekMaterialsDescription)) {
throw new SecurityException("Material description of the new KEK must differ from the current one");
}
final EncryptionMaterials origKEK;
if (usesKMSKey()) {
origKEK = new KMSEncryptionMaterials(kekMaterialsDescription.get(KMSEncryptionMaterials.CUSTOMER_MASTER_KEY_ID));
} else {
origKEK = accessor.getEncryptionMaterials(kekMaterialsDescription);
if (origKEK == null) {
throw new CosClientException("Unable to retrieve the origin encryption materials");
}
}
SecretKey cek = cek(encryptedCEK, keyWrappingAlgorithm, origKEK, p, getContentCryptoScheme(), kms);
ContentCryptoMaterial output = create(// must use same
cek, // must use same
cipherLite.getIV(), // must use same
newKEK, // must use same
getContentCryptoScheme(), // target scheme used to recreate the content crypto material
targetScheme, p, kms, req);
if (Arrays.equals(output.encryptedCEK, encryptedCEK)) {
throw new SecurityException("The new KEK must differ from the original");
}
return output;
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class ContentCryptoMaterial method fromObjectMetadata1.
private static ContentCryptoMaterial fromObjectMetadata1(Map<String, String> userMeta, EncryptionMaterialsAccessor kekMaterialAccessor, Provider securityProvider, long[] range, boolean keyWrapExpected, QCLOUDKMS kms) {
String b64SecuredKey = userMeta.get(Headers.ENCRYPTION_KEY);
if (b64SecuredKey == null) {
throw new CosClientException("Content encrypting key not found.");
}
byte[] securedKey = Base64.decode(b64SecuredKey);
String b64SecuredIV = userMeta.get(Headers.ENCRYPTION_START);
if (b64SecuredIV == null) {
throw new CosClientException("Content encrypting key or IV not found.");
}
byte[] securedIV = Base64.decode(b64SecuredIV);
final String keyWrapAlgo = userMeta.get(Headers.ENCRYPTION_WRAP_ALG);
final String matdescStr = userMeta.get(Headers.ENCRYPTION_MATDESC);
final boolean isKMS = isKMSKeyWrapped(keyWrapAlgo);
final Map<String, String> metadesc = matdescFromJson(matdescStr);
final EncryptionMaterials materials;
if (isKMS) {
if (kekMaterialAccessor instanceof KMSEncryptionMaterialsProvider) {
KMSEncryptionMaterialsProvider kmsMaterialsProvider = (KMSEncryptionMaterialsProvider) kekMaterialAccessor;
materials = kmsMaterialsProvider.getEncryptionMaterials();
} else {
throw new CosClientException("Must use KMSEncryptionMaterials");
}
if (metadesc != null) {
materials.addDescriptions(metadesc);
}
} else {
materials = kekMaterialAccessor == null ? null : kekMaterialAccessor.getEncryptionMaterials(metadesc);
if (materials == null) {
throw new CosClientException("Unable to retrieve the client encryption materials");
}
}
// CEK algorithm
String cekAlgo = userMeta.get(Headers.ENCRYPTION_CEK_ALG);
boolean isRangeGet = range != null;
// The content crypto scheme may vary depending on whether
// it is a range get operation
ContentCryptoScheme contentCryptoScheme = ContentCryptoScheme.fromCEKAlgo(cekAlgo, isRangeGet);
byte[] iv = decryptIV(securedIV, keyWrapAlgo, materials, securityProvider, contentCryptoScheme, kms);
if (isRangeGet) {
// Adjust the IV as needed
iv = contentCryptoScheme.adjustIV(iv, range[0]);
}
// Unwrap or decrypt the CEK
if (keyWrapExpected && keyWrapAlgo == null)
throw newKeyWrapException();
SecretKey cek = cek(securedKey, keyWrapAlgo, materials, securityProvider, contentCryptoScheme, kms);
return new ContentCryptoMaterial(metadesc, securedKey, keyWrapAlgo, contentCryptoScheme.createCipherLite(cek, iv, Cipher.DECRYPT_MODE, securityProvider), null);
}
Aggregations