use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class COSClient method uploadObjectInternal.
protected <UploadObjectRequest extends PutObjectRequest> ObjectMetadata uploadObjectInternal(UploadMode uploadMode, UploadObjectRequest uploadObjectRequest) throws CosClientException, CosServiceException {
rejectNull(uploadObjectRequest, "The PutObjectRequest parameter must be specified when uploading an object");
rejectNull(clientConfig.getRegion(), "region is null, region in clientConfig must be specified when uploading an object");
final File file = uploadObjectRequest.getFile();
final InputStream isOrig = uploadObjectRequest.getInputStream();
final String bucketName = uploadObjectRequest.getBucketName();
final String key = uploadObjectRequest.getKey();
ObjectMetadata metadata = uploadObjectRequest.getMetadata();
InputStream input = isOrig;
if (metadata == null)
metadata = new ObjectMetadata();
rejectNull(bucketName, "The bucket name parameter must be specified when uploading an object");
rejectNull(key, "The key parameter must be specified when uploading an object");
// information from it to auto-configure a few options
if (file == null) {
// unlimited mark-and-reset
if (input != null)
input = ReleasableInputStream.wrap(input);
} else {
// Always set the content length, even if it's already set
metadata.setContentLength(file.length());
final long maxAllowdSingleFileSize = 5 * 1024L * 1024L * 1024L;
if (file.length() > maxAllowdSingleFileSize) {
throw new CosClientException("max size 5GB is allowed by putObject Method, your filesize is " + file.length() + ", please use transferManager to upload big file!");
}
final boolean calculateMD5 = metadata.getContentMD5() == null;
if (calculateMD5 && !skipMd5CheckStrategy.skipServerSideValidation(uploadObjectRequest)) {
try {
String contentMd5_b64 = Md5Utils.md5AsBase64(file);
metadata.setContentMD5(contentMd5_b64);
} catch (Exception e) {
throw new CosClientException("Unable to calculate MD5 hash: " + e.getMessage(), e);
}
}
input = ResettableInputStream.newResettableInputStream(file, "Unable to find file to upload");
}
final ObjectMetadata returnedMetadata;
MD5DigestCalculatingInputStream md5DigestStream = null;
try {
CosHttpRequest<UploadObjectRequest> request = null;
if (uploadMode.equals(UploadMode.PUT_OBJECT)) {
request = createRequest(bucketName, key, uploadObjectRequest, HttpMethodName.PUT);
} else if (uploadMode.equals(UploadMode.APPEND_OBJECT)) {
request = createRequest(bucketName, key, uploadObjectRequest, HttpMethodName.POST);
AppendObjectRequest appendObjectRequest = (AppendObjectRequest) uploadObjectRequest;
String positionStr = String.valueOf(appendObjectRequest.getPosition());
request.addParameter("append", null);
request.addParameter("position", positionStr);
}
if (uploadObjectRequest.getAccessControlList() != null) {
addAclHeaders(request, uploadObjectRequest.getAccessControlList());
} else if (uploadObjectRequest.getCannedAcl() != null) {
request.addHeader(Headers.COS_CANNED_ACL, uploadObjectRequest.getCannedAcl().toString());
}
if (uploadObjectRequest.getStorageClass() != null) {
request.addHeader(Headers.STORAGE_CLASS, uploadObjectRequest.getStorageClass());
}
if (uploadObjectRequest.getRedirectLocation() != null) {
request.addHeader(Headers.REDIRECT_LOCATION, uploadObjectRequest.getRedirectLocation());
if (input == null) {
input = new ByteArrayInputStream(new byte[0]);
}
}
// Populate the SSE-C parameters to the request header
populateSSE_C(request, uploadObjectRequest.getSSECustomerKey());
// Populate the SSE KMS parameters to the request header
populateSSE_KMS(request, uploadObjectRequest.getSSECOSKeyManagementParams());
// Populate the traffic limit parameter to the request header
populateTrafficLimit(request, uploadObjectRequest.getTrafficLimit());
// Use internal interface to differentiate 0 from unset.
final Long contentLength = (Long) metadata.getRawMetadataValue(Headers.CONTENT_LENGTH);
if (contentLength == null) {
/*
* There's nothing we can do except for let the HTTP client buffer the input stream
* contents if the caller doesn't tell us how much data to expect in a stream since
* we have to explicitly tell how much we're sending before we start sending any of
* it.
*/
log.warn("No content length specified for stream data. " + "Stream contents will be buffered in memory and could result in " + "out of memory errors.");
} else {
final long expectedLength = contentLength.longValue();
final long maxAllowdSingleFileSize = 5 * 1024L * 1024L * 1024L;
if (expectedLength > maxAllowdSingleFileSize) {
throw new CosClientException("max size 5GB is allowed by putObject Method, your filesize is " + expectedLength + ", please use transferManager to upload big file!");
}
if (expectedLength >= 0) {
// Performs length check on the underlying data stream.
// For COS encryption client, the underlying data stream here
// refers to the cipher-text data stream (ie not the underlying
// plain-text data stream which in turn may have been wrapped
// with it's own length check input stream.)
LengthCheckInputStream lcis = new // expected
LengthCheckInputStream(// expected
input, // expected
expectedLength, // uploaded
EXCLUDE_SKIPPED_BYTES);
input = lcis;
}
}
if (metadata.getContentMD5() == null && !skipMd5CheckStrategy.skipClientSideValidationPerRequest(uploadObjectRequest)) {
/*
* If the user hasn't set the content MD5, then we don't want to buffer the whole
* stream in memory just to calculate it. Instead, we can calculate it on the fly
* and validate it with the returned ETag from the object upload.
*/
input = md5DigestStream = new MD5DigestCalculatingInputStream(input);
}
populateRequestMetadata(request, metadata);
request.setContent(input);
try {
if (uploadObjectRequest.getPicOperations() != null) {
request.addHeader(Headers.PIC_OPERATIONS, Jackson.toJsonString(uploadObjectRequest.getPicOperations()));
returnedMetadata = invoke(request, new ResponseHeaderHandlerChain<ObjectMetadata>(new Unmarshallers.ImagePersistenceUnmarshaller(), new CosMetadataResponseHandler()));
} else {
returnedMetadata = invoke(request, new CosMetadataResponseHandler());
}
} catch (Throwable t) {
throw Throwables.failure(t);
}
} finally {
CosDataSource.Utils.cleanupDataSource(uploadObjectRequest, file, isOrig, input, log);
}
String contentMd5 = metadata.getContentMD5();
if (md5DigestStream != null) {
contentMd5 = Base64.encodeAsString(md5DigestStream.getMd5Digest());
}
final String etag = returnedMetadata.getETag();
if (contentMd5 != null && uploadMode.equals(UploadMode.PUT_OBJECT) && !skipMd5CheckStrategy.skipClientSideValidationPerPutResponse(returnedMetadata)) {
byte[] clientSideHash = BinaryUtils.fromBase64(contentMd5);
byte[] serverSideHash = null;
try {
serverSideHash = BinaryUtils.fromHex(etag);
} catch (DecoderException e) {
throw new CosClientException("Unable to verify integrity of data upload. " + "Client calculated content hash (contentMD5: " + contentMd5 + " in base 64) didn't match hash (etag: " + etag + " in hex) calculated by COS . " + "You may need to delete the data stored in COS . (metadata.contentMD5: " + metadata.getContentMD5() + ", bucketName: " + bucketName + ", key: " + key + ")");
}
if (!Arrays.equals(clientSideHash, serverSideHash)) {
throw new CosClientException("Unable to verify integrity of data upload. " + "Client calculated content hash (contentMD5: " + contentMd5 + " in base 64) didn't match hash (etag: " + etag + " in hex) calculated by COS . " + "You may need to delete the data stored in COS . (metadata.contentMD5: " + metadata.getContentMD5() + ", bucketName: " + bucketName + ", key: " + key + ")");
}
}
return returnedMetadata;
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class COSClient method setContent.
private void setContent(CosHttpRequest<?> request, byte[] content, String contentType, boolean setMd5) {
request.setContent(new ByteArrayInputStream(content));
request.addHeader("Content-Length", Integer.toString(content.length));
request.addHeader("Content-Type", contentType);
if (setMd5) {
try {
byte[] md5 = Md5Utils.computeMD5Hash(content);
String md5Base64 = BinaryUtils.toBase64(md5);
request.addHeader("Content-MD5", md5Base64);
} catch (Exception e) {
throw new CosClientException("Couldn't compute md5 sum", e);
}
}
}
use of com.qcloud.cos.exception.CosClientException in project cos-java-sdk-v5 by tencentyun.
the class ContentCryptoMaterial method cek.
/**
* Returns the content encrypting key unwrapped or decrypted. Note if KMS is used for key
* protection, a remote call will be made to KMS to decrypt the ciphertext blob.
*
* @param cekSecured the content encrypting key in wrapped or encrypted form; must not be null
* @param keyWrapAlgo key wrapping algorithm; or null if direct encryption instead of key
* wrapping is used
* @param materials the client key encrypting key material for the content encrypting key
* @param securityProvider security provider or null if the default security provider of the JCE
* is used
*/
private static SecretKey cek(byte[] cekSecured, String keyWrapAlgo, EncryptionMaterials materials, Provider securityProvider, ContentCryptoScheme contentCryptoScheme, QCLOUDKMS kms) {
if (isKMSKeyWrapped(keyWrapAlgo))
return cekByKMS(cekSecured, keyWrapAlgo, materials, contentCryptoScheme, kms);
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.UNWRAP_MODE, kek);
return (SecretKey) cipher.unwrap(cekSecured, keyWrapAlgo, Cipher.SECRET_KEY);
}
// 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);
byte[] decryptedSymmetricKeyBytes = cipher.doFinal(cekSecured);
return new SecretKeySpec(decryptedSymmetricKeyBytes, JceEncryptionConstants.SYMMETRIC_KEY_ALGORITHM);
} 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
* material-descriptions. The purpose is to re-encrypt the CEK under a different KEK.
*
* Note network calls are involved if the CEK has been or is to be protected by KMS.
*
* @param newKEKMatDesc material descriptions for the new KEK; never null
* @param accessor used to retrieve the KEK given the corresponding material description
* @param targetScheme the target crypto scheme to be used for key wrapping, etc.
* @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(Map<String, String> newKEKMatDesc, EncryptionMaterialsAccessor accessor, COSCryptoScheme targetScheme, Provider p, QCLOUDKMS kms, CosServiceRequest req) {
if (!usesKMSKey() && newKEKMatDesc.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");
}
}
EncryptionMaterials newKEK = accessor.getEncryptionMaterials(newKEKMatDesc);
if (newKEK == null) {
throw new CosClientException("No material available with the description " + newKEKMatDesc + " from the encryption material provider");
}
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(), // scheme
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 fromObjectMetadata0.
/**
* @return a non-null content crypto material.
*/
private static ContentCryptoMaterial fromObjectMetadata0(ObjectMetadata metadata, EncryptionMaterialsAccessor kekMaterialAccessor, Provider securityProvider, long[] range, boolean keyWrapExpected, QCLOUDKMS kms) {
// CEK and IV
Map<String, String> userMeta = metadata.getUserMetadata();
// new version has different header
if (userMeta.get(Headers.ENCRYPTION_KEY) != null) {
return fromObjectMetadata1(userMeta, kekMaterialAccessor, securityProvider, range, keyWrapExpected, kms);
}
String b64key = userMeta.get(Headers.CRYPTO_KEY_V2);
if (b64key == null) {
b64key = userMeta.get(Headers.CRYPTO_KEY);
if (b64key == null)
throw new CosClientException("Content encrypting key not found.");
}
byte[] cekWrapped = Base64.decode(b64key);
// byte[] iv = userMeta.get(Headers.CRYPTO_IV).getBytes();
byte[] iv = Base64.decode(userMeta.get(Headers.CRYPTO_IV));
if (cekWrapped == null || iv == null) {
throw new CosClientException("Content encrypting key or IV not found.");
}
// Material description
String matdescStr = userMeta.get(Headers.MATERIALS_DESCRIPTION);
final String keyWrapAlgo = userMeta.get(Headers.CRYPTO_KEYWRAP_ALGORITHM);
final boolean isKMS = isKMSKeyWrapped(keyWrapAlgo);
final Map<String, String> core = matdescFromJson(matdescStr);
final EncryptionMaterials materials;
if (isKMS) {
materials = new KMSEncryptionMaterials(core.get(KMSEncryptionMaterials.CUSTOMER_MASTER_KEY_ID));
materials.addDescriptions(core);
} else {
materials = kekMaterialAccessor == null ? null : kekMaterialAccessor.getEncryptionMaterials(core);
if (materials == null) {
throw new CosClientException("Unable to retrieve the client encryption materials");
}
}
// CEK algorithm
String cekAlgo = userMeta.get(Headers.CRYPTO_CEK_ALGORITHM);
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);
if (isRangeGet) {
// Adjust the IV as needed
iv = contentCryptoScheme.adjustIV(iv, range[0]);
} else {
// Validate the tag length supported
int tagLenExpected = contentCryptoScheme.getTagLengthInBits();
if (tagLenExpected > 0) {
String s = userMeta.get(Headers.CRYPTO_TAG_LENGTH);
int tagLenActual = Integer.parseInt(s);
if (tagLenExpected != tagLenActual) {
throw new CosClientException("Unsupported tag length: " + tagLenActual + ", expected: " + tagLenExpected);
}
}
}
// Unwrap or decrypt the CEK
if (keyWrapExpected && keyWrapAlgo == null)
throw newKeyWrapException();
SecretKey cek = cek(cekWrapped, keyWrapAlgo, materials, securityProvider, contentCryptoScheme, kms);
return new ContentCryptoMaterial(core, cekWrapped, keyWrapAlgo, contentCryptoScheme.createCipherLite(cek, iv, Cipher.DECRYPT_MODE, securityProvider), null);
}
Aggregations