A criptografia no lado do cliente criptografa objetos localmente antes do envio ao OSS. Somente o proprietário da CMK pode descriptografar os dados, o que fortalece a segurança durante a transmissão e o armazenamento.
Aviso legal
Ao usar a criptografia no lado do cliente, garanta a integridade e a validade da CMK. Se a CMK for usada incorretamente ou perdida devido a manutenção inadequada, você será responsável por todas as perdas e consequências causadas por falhas na descriptografia.
Ao copiar ou migrar dados criptografados, garanta a integridade e a validade dos metadados do objeto. Caso os metadados criptografados estejam incorretos ou sejam perdidos por manutenção inadequada, você responderá por todas as perdas e consequências decorrentes de falhas na descriptografia dos dados.
Cenários
Dados altamente sensíveis: criptografe PII, registros financeiros, dados de saúde e outras informações sensíveis antes que saiam do ambiente local. Essa prática protege os dados originais mesmo se forem interceptados durante a transmissão.
Requisitos de conformidade: regulamentações como HIPAA e GDPR exigem gerenciamento rigoroso de criptografia para dados em plataformas de terceiros. A criptografia no lado do cliente atende a esses requisitos porque os usuários gerenciam as CMKs, que nunca são transmitidas pela rede nem expostas aos provedores de service cloud.
Controle total da criptografia: mantenha controle completo sobre o processo de criptografia, incluindo a seleção de algoritmos e o gerenciamento e rotação de CMKs. Apenas usuários autorizados podem descriptografar e acessar os dados.
Migração de dados entre regiões: a criptografia no lado do cliente mantém os dados criptografados antes e depois da migração entre regiões, reforçando a segurança durante a transmissão pela Internet.
Observações de uso
Este tópico usa o endpoint público da região China (Hangzhou). Para acessar o OSS a partir de outros service Alibaba Cloud na mesma região, use um endpoint interno. Para obter detalhes sobre as regiões e endpoints suportados, consulte Regions and endpoints.
As credenciais de acesso neste tópico são obtidas de variáveis de ambiente. Para mais informações, consulte 配置访问凭证.
Este tópico demonstra a criação de uma instância OSSClient com um endpoint do OSS. Para configurações alternativas, como usar um domínio personalizado ou autenticar-se com credenciais do Security Token Service (STS), consulte Client configuration.
Informações básicas
Na criptografia no lado do cliente, uma chave de dados aleatória é gerada para cada objeto para executar a criptografia simétrica. O cliente usa uma CMK para criptografar essa chave de dados aleatória. A chave de dados criptografada é enviada como parte dos metadados do objeto e armazenada no servidor OSS. Ao baixar um objeto criptografado, o cliente utiliza a CMK para descriptografar a chave de dados aleatória e, em seguida, usa a chave descriptografada para decifrar o objeto. Para garantir a segurança dos dados, a CMK é usada apenas no cliente, sem ser transmitida pela rede ou armazenada no servidor.
A criptografia no lado do cliente suporta upload multipartido para objetos maiores que 5 GB. Especifique o tamanho total do objeto e o tamanho de cada parte. Todas as partes, exceto a última, devem ter o mesmo tamanho e ser múltiplas de 16 bytes.
Após enviar objetos criptografados no lado do cliente, os metadados relacionados à criptografia ficam protegidos e não podem ser modificados pela chamada da operação CopyObject.
Métodos de criptografia
Atualmente, uma chave mestra é utilizada das duas formas seguintes:
-
CMKs gerenciadas pelo KMS
Ao usar uma CMK gerenciada no Key Management Service (KMS) para criptografia no lado do cliente, forneça o ID da CMK ao OSS SDK for Java.
-
CMKs baseadas em RSA gerenciadas por você
Ao utilizar uma CMK gerenciada por você para criptografia no lado do cliente, envie a chave pública e a chave privada da sua CMK ao OSS SDK for Java como parâmetros.
Os métodos de criptografia acima previnem vazamentos e protegem seus dados no cliente. Mesmo que seus dados vazem, terceiros não conseguirão descriptografá-los.
Metadados de objeto relacionados à criptografia no lado do cliente
|
Parâmetro |
Descrição |
Obrigatório |
|
x-oss-meta-client-side-encryption-key |
A chave de dados criptografada, uma string criptografada por CMK e codificada em Base64. |
Sim |
|
x-oss-meta-client-side-encryption-start |
O vetor de inicialização gerado aleatoriamente para criptografia de dados, uma string criptografada por CMK e codificada em Base64. |
Sim |
|
x-oss-meta-client-side-encryption-cek-alg |
O algoritmo usado para criptografar dados. |
Sim |
|
x-oss-meta-client-side-encryption-wrap-alg |
O algoritmo usado para criptografar a chave de dados. |
Sim |
|
x-oss-meta-client-side-encryption-matdesc |
A descrição da CMK no formato JSON. Aviso
Configure uma descrição para cada CMK e armazene o mapeamento entre CMK e descrição. Uma CMK sem descrição não pode ser substituída. |
Não |
|
x-oss-meta-client-side-encryption-unencrypted-content-length |
O comprimento dos dados antes da criptografia. Não é gerado se Content-Length não for especificado. |
Não |
|
x-oss-meta-client-side-encryption-unencrypted-content-md5 |
O hash MD5 antes da criptografia. Não é gerado se Content-MD5 não for especificado. |
Não |
|
x-oss-meta-client-side-encryption-data-size |
O tamanho total dos dados para upload multipartido, especificado quando init_multipart é chamado. |
Sim (para upload multipartido) |
|
x-oss-meta-client-side-encryption-part-size |
O tamanho da parte para upload multipartido, especificado quando init_multipart é chamado. Importante
O tamanho da parte deve ser um múltiplo de 16. |
Sim (para upload multipartido) |
OpenSSL
Por padrão, o OpenSSL 3.x gera PRIVATE_PKCS8_PEM. Para gerar PRIVATE_PKCS1_PEM, adicione a opção -traditional conforme descrito na documentação do OpenSSL.
Crie um cliente para criptografia no lado do cliente
Para criar um cliente para criptografia baseada em RSA ou KMS, use o OSS SDK for Java 3.9.1 ou posterior e adicione a biblioteca Bouncy Castle (bcprov-jdk15on) ao seu projeto Maven:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.62</version>
</dependency>
Se o erro java.security.InvalidKeyException: Illegal key size or default parameters for retornado, adicione os arquivos de política de jurisdição de força ilimitada do Oracle JCE ao seu ambiente JRE.
Baixe o arquivo correspondente à sua versão do JDK e extraia-o no diretório jre/lib/security.
Crie um cliente para criptografia baseada em RSA
Antes de criar um cliente para criptografia baseada em RSA, crie um par de chaves assimétricas. O OSS SDK for Java fornece métodos para converter strings de chave privada PEM PKCS #1 ou PKCS #8 em chaves privadas RSA, e strings de chave pública PEM X.509 em chaves públicas RSA.
Utilize os seguintes métodos para converter as chaves:
RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(String privateKeyStr);
RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS8(String privateKeyStr);
RSAPublicKey SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(String publicKeyStr);
Código de exemplo para criar um cliente de criptografia baseada em RSA:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// You can run the following commands to separately generate the PEM files for the private key and public key. Then, set the values of PRIVATE_PKCS1_PEM and PUBLIC_X509_PEM to the strings included in the PEM files for the private key and public key.
// openssl genrsa -out private_key.pem 2048
// openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for RSA-based encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Write your business code.
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Crie um cliente para criptografia baseada em KMS
Para criar um cliente para criptografia baseada em KMS, adicione a biblioteca Bouncy Castle (bcprov-jdk15on) e a biblioteca KMS (kms-transfer-client) ao seu projeto Maven:
<dependency>
<groupId>com.aliyun.kms</groupId>
<artifactId>kms-transfer-client</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>
Código de exemplo para criar um cliente de criptografia baseada em KMS:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.crypto.ContentCryptoMaterialRW;
import com.aliyun.oss.crypto.EncryptionMaterials;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.kms.model.v20160120.DecryptRequest;
import com.aliyuncs.kms.model.v20160120.DecryptResponse;
import com.aliyuncs.kms.model.v20160120.EncryptRequest;
import com.aliyuncs.kms.model.v20160120.EncryptResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the CMK ID. Example: e1935511-cf88-1123-a0f8-1be8d251****.
String cmk = "e1935511-cf88-1123-a0f8-1be8d251****";
// Specify the region to which the CMK belongs. Example: cn-hangzhou.
String region = "cn-hangzhou";
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description and one region for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create KMS encryption materials.
KmsEncryptionMaterialsV3 encryptionMaterials = new KmsEncryptionMaterialsV3(region, cmk, matDesc);
encryptionMaterials.setKmsCredentialsProvider(credentialsProvider);
// To download and decrypt objects encrypted by using other CMKs, add the region names and descriptions of the CMKs to the KMS encryption materials.
// encryptionMaterials.addKmsDescMaterial(<otherKmsRegion>, <otherKmsMatDesc>);
// If the account used to access KMS is different from the account used to access OSS and you want to download and decrypt objects encrypted by using other CMKs, add the region names, credentials, and descriptions of the CMKs to the KMS encryption materials.
// encryptionMaterials.addKmsDescMaterial(<otherKmsRegion>, <otherKmsCredentialsProvider>, <otherKmsMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Write your business code.
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
class KmsEncryptionMaterialsV3 implements EncryptionMaterials {
private static final String KEY_WRAP_ALGORITHM = "KMS/ALICLOUD";
private String region;
private String cmk;
CredentialsProvider credentialsProvider;
private final Map<String, String> desc;
private final LinkedHashMap<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> kmsDescMaterials =
new LinkedHashMap<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>>();
public KmsEncryptionMaterialsV3(String region, String cmk) {
assertParameterNotNull(region, "kms region");
assertParameterNotNull(cmk, "kms cmk");
this.region = region;
this.cmk = cmk;
this.desc = new HashMap<String, String>();
}
public KmsEncryptionMaterialsV3(String region, String cmk, Map<String, String> desc) {
assertParameterNotNull(region, "kms region");
assertParameterNotNull(region, "kms cmk");
this.region = region;
this.cmk = cmk;
this.desc = (desc == null) ? new HashMap<String, String>() : new HashMap<String, String>(desc);
}
private final class KmsClientSuite {
private String region;
private CredentialsProvider credentialsProvider;
KmsClientSuite(String region, CredentialsProvider credentialsProvider) {
this.region = region;
this.credentialsProvider = credentialsProvider;
}
}
public void setKmsCredentialsProvider(CredentialsProvider credentialsProvider) {
this.credentialsProvider = credentialsProvider;
kmsDescMaterials.put(new KmsEncryptionMaterialsV3.KmsClientSuite(region, credentialsProvider), desc);
}
private DefaultAcsClient createKmsClient(String region, CredentialsProvider credentialsPorvider) {
Credentials credentials = credentialsPorvider.getCredentials();
IClientProfile profile = DefaultProfile.getProfile(region, credentials.getAccessKeyId(),
credentials.getSecretAccessKey(), credentials.getSecurityToken());
return new KmsTransferAcsClient(profile);
}
private EncryptResponse encryptPlainText(String keyId, String plainText) throws ClientException {
DefaultAcsClient kmsClient = createKmsClient(region, credentialsProvider);
final EncryptRequest encReq = new EncryptRequest();
encReq.setSysProtocol(ProtocolType.HTTPS);
encReq.setAcceptFormat(FormatType.JSON);
encReq.setSysMethod(MethodType.POST);
encReq.setKeyId(keyId);
encReq.setPlaintext(plainText);
final EncryptResponse encResponse;
try {
encResponse = kmsClient.getAcsResponse(encReq);
} catch (Exception e) {
throw new ClientException("the kms client encrypt data failed." + e.getMessage(), e);
}
return encResponse;
}
private DecryptResponse decryptCipherBlob(KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite, String cipherBlob)
throws ClientException {
final DefaultAcsClient kmsClient = createKmsClient(kmsClientSuite.region, kmsClientSuite.credentialsProvider);
final DecryptRequest decReq = new DecryptRequest();
decReq.setSysProtocol(ProtocolType.HTTPS);
decReq.setAcceptFormat(FormatType.JSON);
decReq.setSysMethod(MethodType.POST);
decReq.setCiphertextBlob(cipherBlob);
final DecryptResponse decResponse;
try {
decResponse = kmsClient.getAcsResponse(decReq);
} catch (Exception e) {
throw new ClientException("The kms client decrypt data faild." + e.getMessage(), e);
}
return decResponse;
}
public void addKmsDescMaterial(String region, Map<String, String> description) {
addKmsDescMaterial(region, credentialsProvider, description);
}
public synchronized void addKmsDescMaterial(String region, CredentialsProvider credentialsProvider, Map<String, String> description) {
assertParameterNotNull(region, "region");
assertParameterNotNull(credentialsProvider, "credentialsProvider");
KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite = new KmsEncryptionMaterialsV3.KmsClientSuite(region, credentialsProvider);
if (description != null) {
kmsDescMaterials.put(kmsClientSuite, new HashMap<String, String>(description));
} else {
kmsDescMaterials.put(kmsClientSuite, new HashMap<String, String>());
}
}
private KmsEncryptionMaterialsV3.KmsClientSuite findKmsClientSuiteByDescription(Map<String, String> desc) {
if (desc == null) {
return null;
}
for (Map.Entry<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> entry : kmsDescMaterials.entrySet()) {
if (desc.equals(entry.getValue())) {
return entry.getKey();
}
}
return null;
}
private <K, V> Map.Entry<K, V> getTailByReflection(LinkedHashMap<K, V> map)
throws NoSuchFieldException, IllegalAccessException {
Field tail = map.getClass().getDeclaredField("tail");
tail.setAccessible(true);
return (Map.Entry<K, V>) tail.get(map);
}
@Override
public void encryptCEK(ContentCryptoMaterialRW contentMaterialRW) {
try {
assertParameterNotNull(contentMaterialRW, "contentMaterialRW");
assertParameterNotNull(contentMaterialRW.getIV(), "contentMaterialRW#getIV");
assertParameterNotNull(contentMaterialRW.getCEK(), "contentMaterialRW#getCEK");
byte[] iv = contentMaterialRW.getIV();
EncryptResponse encryptresponse = encryptPlainText(cmk, BinaryUtil.toBase64String(iv));
byte[] encryptedIV = BinaryUtil.fromBase64String(encryptresponse.getCiphertextBlob());
SecretKey cek = contentMaterialRW.getCEK();
encryptresponse = encryptPlainText(cmk, BinaryUtil.toBase64String(cek.getEncoded()));
byte[] encryptedCEK = BinaryUtil.fromBase64String(encryptresponse.getCiphertextBlob());
contentMaterialRW.setEncryptedCEK(encryptedCEK);
contentMaterialRW.setEncryptedIV(encryptedIV);
contentMaterialRW.setKeyWrapAlgorithm(KEY_WRAP_ALGORITHM);
contentMaterialRW.setMaterialsDescription(desc);
} catch (Exception e) {
throw new ClientException("Kms encrypt CEK IV error. "
+ "Please check your cmk, region, accessKeyId and accessSecretId." + e.getMessage(), e);
}
}
@Override
public void decryptCEK(ContentCryptoMaterialRW contentMaterialRW) {
assertParameterNotNull(contentMaterialRW, "ContentCryptoMaterialRW");
assertParameterNotNull(contentMaterialRW.getEncryptedCEK(), "ContentCryptoMaterialRW#getEncryptedCEK");
assertParameterNotNull(contentMaterialRW.getEncryptedIV(), "ContentCryptoMaterialRW#getEncryptedIV");
assertParameterNotNull(contentMaterialRW.getKeyWrapAlgorithm(), "ContentCryptoMaterialRW#getKeyWrapAlgorithm");
if (!contentMaterialRW.getKeyWrapAlgorithm().toLowerCase().equals(KEY_WRAP_ALGORITHM.toLowerCase())) {
throw new ClientException(
"Unrecognize your object key wrap algorithm: " + contentMaterialRW.getKeyWrapAlgorithm());
}
try {
KmsEncryptionMaterialsV3.KmsClientSuite kmsClientSuite = findKmsClientSuiteByDescription(contentMaterialRW.getMaterialsDescription());
if (kmsClientSuite == null) {
Map.Entry<KmsEncryptionMaterialsV3.KmsClientSuite, Map<String, String>> entry = getTailByReflection(kmsDescMaterials);
kmsClientSuite = entry.getKey();
}
DecryptResponse decryptIvResp = decryptCipherBlob(kmsClientSuite,
BinaryUtil.toBase64String(contentMaterialRW.getEncryptedIV()));
byte[] iv = BinaryUtil.fromBase64String(decryptIvResp.getPlaintext());
DecryptResponse decryptCEKResp = decryptCipherBlob(kmsClientSuite,
BinaryUtil.toBase64String(contentMaterialRW.getEncryptedCEK()));
byte[] cekBytes = BinaryUtil.fromBase64String(decryptCEKResp.getPlaintext());
SecretKey cek = new SecretKeySpec(cekBytes, "");
contentMaterialRW.setCEK(cek);
contentMaterialRW.setIV(iv);
} catch (Exception e) {
throw new ClientException("Unable to decrypt content secured key and iv. "
+ "Please check your kms region and materails description." + e.getMessage(), e);
}
}
private void assertParameterNotNull(Object parameterValue, String errorMessage) {
if (parameterValue == null)
throw new IllegalArgumentException(errorMessage);
}
}
As seções a seguir apresentam códigos de exemplo para criptografia no lado do cliente baseada em RSA em upload e download simples, upload multipartido e download por intervalo.
A criptografia no lado do cliente baseada em KMS difere da criptografia baseada em RSA apenas na forma como o OSSEncryptionClient é criado.
Criptografia baseada em RSA: Upload e download simples
Use CMKs para criptografar objetos durante o upload simples e descriptografá-los durante o download simples:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.OSSObject;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampleobject.txt";
String content = "Hello OSS!";
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Encrypt and upload the object.
ossEncryptionClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// Download the object. The object is automatically decrypted.
OSSObject ossObject = ossEncryptionClient.getObject(bucketName, objectName);
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
// Check whether the decrypted content is the same as the uploaded object in plaintext.
System.out.println("Put plain text: " + content);
System.out.println("Get and decrypted text: " + buffer.toString());
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Criptografia baseada em RSA: Upload multipartido
Use uma CMK baseada em RSA para criptografar objetos durante o upload multipartido:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.MultipartUploadCryptoContext;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.io.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampleobject.txt";
// Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt.
String localFile = "D:\\localpath\\examplefile.txt";
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Create a MultipartUploadCryptoContext object and specify the object size and part size. The part size must be a multiple of 16 bytes.
File file = new File(localFile);
long fileLength = file.length();
final long partSize = 100 * 1024L; // 100K
MultipartUploadCryptoContext context = new MultipartUploadCryptoContext();
context.setPartSize(partSize);
context.setDataSize(fileLength);
// Initiate a multipart upload task.
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, objectName);
// Use the created MultipartUploadCryptoContext object.
InitiateMultipartUploadResult upresult = ossEncryptionClient.initiateMultipartUpload(initiateMultipartUploadRequest, context);
String uploadId = upresult.getUploadId();
// Create a collection of PartETags. A PartETag consists of the part number and ETag of the part.
List<PartETag> partETags = new ArrayList<PartETag>();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// Upload all parts of the object.
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
InputStream instream = new FileInputStream(file);
instream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(objectName);
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(instream);
uploadPartRequest.setPartSize(curPartSize);
uploadPartRequest.setPartNumber( i + 1);
// Use the created MultipartUploadCryptoContext object.
UploadPartResult uploadPartResult = ossEncryptionClient.uploadPart(uploadPartRequest, context);
partETags.add(uploadPartResult.getPartETag());
}
// Complete the multipart upload task.
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
ossEncryptionClient.completeMultipartUpload(completeMultipartUploadRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Criptografia baseada em RSA: Upload retomável
Use uma CMK baseada em RSA para criptografar objetos durante o upload retomável:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampleobject.txt";
// Specify the full path of the local file. Example: D:\\localpath\\examplefile.txt.
String localFile = "D:\\localpath\\examplefile.txt";
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Create an UploadFileRequest object.
UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, objectName);
// Specify the path of the object that you want to upload.
uploadFileRequest.setUploadFile(localFile);
// Specify the part size. The valid part size ranges from 100 KB to 5 GB. The default part size is one ten-thousandth of the object size.
uploadFileRequest.setPartSize(100 * 1024);
// Specify whether to enable resumable upload. By default, resumable upload is disabled.
uploadFileRequest.setEnableCheckpoint(true);
// Specify the name for the checkpoint file. If you do not specify a name for the checkpoint file, the default checkpoint file name follows the "localfile.ucp" format. The default checkpoint file is in the same directory as the local file to upload.
// This file stores the information about upload progress. If a part fails to be uploaded, the part upload continues based on the recorded progress. After the object is uploaded, the checkpoint file is deleted.
uploadFileRequest.setCheckpointFile("test-upload.ucp");
// Start resumable upload.
ossEncryptionClient.uploadFile(uploadFileRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Criptografia baseada em RSA: Download retomável
Use uma CMK baseada em RSA para descriptografar objetos durante o download retomável:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampleobject.txt";
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Send a request to start resumable download in which 10 download tasks run concurrently.
DownloadFileRequest downloadFileRequest = new DownloadFileRequest(bucketName, objectName);
downloadFileRequest.setDownloadFile("<yourDownloadFile>");
downloadFileRequest.setPartSize(1 * 1024 * 1024);
downloadFileRequest.setTaskNum(10);
downloadFileRequest.setEnableCheckpoint(true);
downloadFileRequest.setCheckpointFile("<yourCheckpointFile>");
// Start resumable download.
DownloadFileResult downloadRes = ossEncryptionClient.downloadFile(downloadFileRequest);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Criptografia baseada em RSA: Download por intervalo
Use uma CMK baseada em RSA para descriptografar objetos durante o download por intervalo:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.crypto.SimpleRSAEncryptionMaterials;
import com.aliyun.oss.model.*;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path.
String objectName = "exampleobject.txt";
String content = "test-range-get-content-82042795hlnf12s8yhfs976y2nfoshhnsdfsf235bvsmnhtskbcfd!";
// Specify your RSA private key string. You can generate the string by using OpenSSL. The following lines show a sample RSA private key string.
final String PRIVATE_PKCS1_PEM =
"-----BEGIN RSA PRIVATE KEY-----\n" +
"MIICWwIBAAKBgQCokfiAVXXf5ImFzKDw+XO/UByW6mse2QsIgz3ZwBtMNu59fR5z\n" +
"ttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC5MFO1PByrE/MNd5AAfSVba93\n" +
"I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MmR1EKib1Id8hpooY5xaQIDAQAB\n" +
"AoGAOPUZgkNeEMinrw31U3b2JS5sepG6oDG2CKpPu8OtdZMaAkzEfVTJiVoJpP2Y\n" +
"nPZiADhFW3e0ZAnak9BPsSsySRaSNmR465cG9tbqpXFKh9Rp/sCPo4Jq2n65yood\n" +
"JBrnGr6/xhYvNa14sQ6xjjfSgRNBSXD1XXNF4kALwgZyCAECQQDV7t4bTx9FbEs5\n" +
"36nAxPsPM6aACXaOkv6d9LXI7A0J8Zf42FeBV6RK0q7QG5iNNd1WJHSXIITUizVF\n" +
"6aX5NnvFAkEAybeXNOwUvYtkgxF4s28s6gn11c5HZw4/a8vZm2tXXK/QfTQrJVXp\n" +
"VwxmSr0FAajWAlcYN/fGkX1pWA041CKFVQJAG08ozzekeEpAuByTIOaEXgZr5MBQ\n" +
"gBbHpgZNBl8Lsw9CJSQI15wGfv6yDiLXsH8FyC9TKs+d5Tv4Cvquk0efOQJAd9OC\n" +
"lCKFs48hdyaiz9yEDsc57PdrvRFepVdj/gpGzD14mVerJbOiOF6aSV19ot27u4on\n" +
"Td/3aifYs0CveHzFPQJAWb4LCDwqLctfzziG7/S7Z74gyq5qZF4FUElOAZkz123E\n" +
"yZvADwuz/4aK0od0lX9c4Jp7Mo5vQ4TvdoBnPuGo****\n" +
"-----END RSA PRIVATE KEY-----";
// Specify your RSA public key string. You can generate the string by using OpenSSL. The following lines show a sample RSA public key string.
final String PUBLIC_X509_PEM =
"-----BEGIN PUBLIC KEY-----\n" +
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCokfiAVXXf5ImFzKDw+XO/UByW\n" +
"6mse2QsIgz3ZwBtMNu59fR5zttSx+8fB7vR4CN3bTztrP9A6bjoN0FFnhlQ3vNJC\n" +
"5MFO1PByrE/MNd5AAfSVba93I6sx8NSk5MzUCA4NJzAUqYOEWGtGBcom6kEF6MnR\n" +
"1EKib1Id8hpooY5xaQID****\n" +
"-----END PUBLIC KEY-----";
// Create an RSA key pair.
RSAPrivateKey privateKey = SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(PRIVATE_PKCS1_PEM);
RSAPublicKey publicKey = SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(PUBLIC_X509_PEM);
KeyPair keyPair = new KeyPair(publicKey, privateKey);
// Specify the description of the CMK. The description cannot be modified after it is specified. You can specify only one description for a CMK.
// If all objects that you want to encrypt share a CMK, you can leave the description of the CMK empty. In this case, the CMK cannot be replaced.
// If you leave the description of the CMK empty, the client cannot determine which CMK to use for decryption.
// We recommend that you specify a description for each CMK and store the mapping relationship between the CMK and the description on the client. The server does not store the mapping relationship.
Map<String, String> matDesc = new HashMap<String, String>();
matDesc.put("desc-key", "desc-value");
// Create RSA encryption materials.
SimpleRSAEncryptionMaterials encryptionMaterials = new SimpleRSAEncryptionMaterials(keyPair, matDesc);
// To download and decrypt objects encrypted by using other CMKs, add these CMKs and their descriptions to the encryption materials.
// encryptionMaterials.addKeyPairDescMaterial(<otherKeyPair>, <otherKeyPairMatDesc>);
// Create a client for client-side encryption.
// Call the shutdown method to release associated resources when the client is no longer in use.
OSSEncryptionClient ossEncryptionClient = new OSSEncryptionClientBuilder().
build(endpoint, credentialsProvider, encryptionMaterials);
try {
// Encrypt and upload the object.
ossEncryptionClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
// Start range download.
int start = 17;
int end = 35;
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objectName);
getObjectRequest.setRange(start, end);
OSSObject ossObject = ossEncryptionClient.getObject(getObjectRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
reader.close();
// Display the downloaded data.
System.out.println("Range-Get plain text:" + content.substring(start, end + 1));
System.out.println("Range-Get decrypted text: " + buffer.toString());
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossEncryptionClient != null) {
ossEncryptionClient.shutdown();
}
}
}
}
Referências
O código de exemplo completo de criptografia no lado do cliente está disponível no GitHub.