Todos los productos
Search
Centro de documentos

Object Storage Service:Cifrado del lado del cliente (OSS SDK for Java 1.0)

Última actualización: Sep 18, 2026

El cifrado del lado del cliente cifra los objetos de forma local antes de cargarlos en OSS. Solo el propietario de la CMK puede descifrar los datos, lo que refuerza la seguridad durante la transmisión y el almacenamiento.

Aviso legal

  • Cuando utilice el cifrado del lado del cliente, asegúrese de mantener la integridad y validez de la CMK. Si la CMK se usa de manera incorrecta o se pierde por un mantenimiento inadecuado, usted será responsable de todas las pérdidas y consecuencias derivadas de los fallos de descifrado.

  • Al copiar o migrar datos cifrados, usted es responsable de la integridad y validez de los metadatos de los objetos. Si los metadatos cifrados son incorrectos o se pierden por un mantenimiento inadecuado, asumirá todas las pérdidas y consecuencias causadas por los fallos al descifrar los datos.

Escenarios

  • Datos altamente sensibles: cifre información de identificación personal (PII), registros financieros, datos de salud y otros datos confidenciales antes de que salgan del entorno local. Esto protege los datos originales incluso si se interceptan durante la transmisión.

  • Requisitos de cumplimiento: normativas como HIPAA y GDPR exigen una gestión estricta del cifrado para los datos alojados en plataformas de terceros. El cifrado del lado del cliente cumple con estos requisitos porque las CMK las gestionan los usuarios, nunca se transmiten por la red ni quedan expuestas a los proveedores de servicios en la nube.

  • Control total del cifrado: mantenga el control absoluto sobre el proceso de cifrado, incluida la selección del algoritmo, así como la gestión y rotación de la CMK. Solo los usuarios autorizados pueden descifrar y acceder a los datos.

  • Migración de datos entre regiones: este método mantiene los datos cifrados antes y después de una migración entre regiones, lo que fortalece la seguridad durante la transmisión por Internet.

Notas de uso

  • En este tema se utiliza el endpoint público de la región China (Hangzhou). Para acceder a OSS desde otros servicios de Alibaba Cloud en la misma región, use un endpoint interno. Para obtener más información sobre las regiones y los endpoints compatibles, consulte Regions and endpoints.

  • Las credenciales de acceso utilizadas en este tema se obtienen de variables de entorno. Para obtener más información, consulte 配置访问凭证.

  • Este tema muestra cómo crear una instancia de OSSClient con un endpoint de OSS. Para conocer configuraciones alternativas, como usar un dominio personalizado o autenticarse con credenciales de Security Token Service (STS), consulte Client configuration.

Contexto

En el cifrado del lado del cliente se genera una clave de datos aleatoria para cada objeto con el fin de aplicar un cifrado simétrico. El cliente utiliza una CMK para cifrar dicha clave de datos aleatoria. La clave de datos cifrada se carga como parte de los metadatos del objeto y se almacena en el servidor de OSS. Cuando se descarga un objeto cifrado, el cliente emplea la CMK para descifrar la clave de datos aleatoria y, posteriormente, usa esa clave descifrada para descifrar el objeto. Para garantizar la seguridad de los datos, la CMK solo se utiliza en el cliente; no se transmite por la red ni se almacena en el servidor.

Importante
  • El cifrado del lado del cliente admite cargas multiparte para objetos mayores a 5 GB. Debe especificar el tamaño total del objeto y el tamaño de cada parte. Todas las partes, excepto la última, deben tener el mismo tamaño y ser múltiplos de 16 bytes.

  • Después de cargar objetos cifrados en el cliente, los metadatos relacionados con el cifrado del lado del cliente quedan protegidos y no se pueden modificar mediante la operación CopyObject.

Métodos de cifrado

Actualmente, una clave maestra se utiliza de las dos maneras siguientes:

  • CMK gestionadas por KMS

    Cuando utilice una CMK gestionada en Key Management Service (KMS) para el cifrado del lado del cliente, debe proporcionar el identificador de la CMK a OSS SDK for Python.

  • CMK basadas en RSA gestionadas por usted

    Si opta por una CMK gestionada por usted para el cifrado del lado del cliente, debe enviar la clave pública y la clave privada de su CMK a OSS SDK for Python como parámetros.

Los métodos de cifrado anteriores le permiten prevenir fugas de información y proteger sus datos en el cliente. Incluso si los datos se filtran, nadie más podrá descifrarlos.

Metadatos de objetos relacionados con el cifrado del lado del cliente

Parámetro

Descripción

Obligatorio

x-oss-meta-client-side-encryption-key

La clave de datos cifrada, una cadena cifrada con la CMK y codificada en Base64.

Sí

x-oss-meta-client-side-encryption-start

El vector de inicialización generado de forma aleatoria para el cifrado de datos, una cadena cifrada con la CMK y codificada en Base64.

Sí

x-oss-meta-client-side-encryption-cek-alg

El algoritmo utilizado para cifrar los datos.

Sí

x-oss-meta-client-side-encryption-wrap-alg

El algoritmo utilizado para cifrar la clave de datos.

Sí

x-oss-meta-client-side-encryption-matdesc

La descripción de la CMK en formato JSON.

Aviso

Configure una descripción para cada CMK y almacene la asignación entre la CMK y su descripción. Una CMK sin descripción no se puede reemplazar.

No

x-oss-meta-client-side-encryption-unencrypted-content-length

La longitud de los datos antes del cifrado. No se genera si no se especifica Content-Length.

No

x-oss-meta-client-side-encryption-unencrypted-content-md5

El hash MD5 antes del cifrado. No se genera si no se especifica Content-MD5.

No

x-oss-meta-client-side-encryption-data-size

El tamaño total de los datos para la carga multiparte, especificado al llamar a init_multipart.

Sí (para cargas multiparte)

x-oss-meta-client-side-encryption-part-size

El tamaño de cada parte para la carga multiparte, especificado al llamar a init_multipart.

Importante

El tamaño de la parte debe ser múltiplo de 16.

Sí (para cargas multiparte)

OpenSSL

De forma predeterminada, OpenSSL 3.x genera PRIVATE_PKCS8_PEM. Para generar PRIVATE_PKCS1_PEM, agregue la opción -traditional tal como se describe en la documentación de OpenSSL.

Crear un cliente para el cifrado del lado del cliente

Nota

Para crear un cliente con cifrado basado en RSA o en KMS, utilice OSS SDK for Java 3.9.1 o una versión posterior y agregue la biblioteca Bouncy Castle (bcprov-jdk15on) a su proyecto de Maven:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.62</version>
</dependency>

Si se devuelve el error java.security.InvalidKeyException: Illegal key size or default parameters, agregue los archivos de directivas jurisdiccionales de fuerza ilimitada JCE de Oracle a su entorno de JRE.

Descargue el archivo correspondiente a su versión de JDK y extráigalo en el directorio jre/lib/security.

Crear un cliente para cifrado basado en RSA

Antes de crear un cliente para el cifrado basado en RSA, genere una key pair asimétrica. OSS SDK for Java proporciona métodos para convertir cadenas de claves privadas PEM PKCS #1 o PKCS #8 en claves privadas RSA, así como cadenas de claves públicas PEM X.509 en claves públicas RSA.

Utilice los siguientes métodos para convertir las claves:

RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS1(String privateKeyStr);

RSAPrivateKey SimpleRSAEncryptionMaterials.getPrivateKeyFromPemPKCS8(String privateKeyStr);

RSAPublicKey SimpleRSAEncryptionMaterials.getPublicKeyFromPemX509(String publicKeyStr);

A continuación se muestra un ejemplo de código para crear un cliente de cifrado basado en 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();
            }
        }
    }
}

Crear un cliente para cifrado basado en KMS

Nota

Para crear un cliente con cifrado basado en KMS, agregue la biblioteca Bouncy Castle (bcprov-jdk15on) y la biblioteca de KMS (kms-transfer-client) a su proyecto de Maven:

<dependency>
    <groupId>com.aliyun.kms</groupId>
    <artifactId>kms-transfer-client</artifactId>
    <version>0.1.0</version>
    <scope>test</scope>
</dependency>

A continuación se muestra un ejemplo de código para crear un cliente de cifrado basado en 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);
    }
}

A continuación se presentan ejemplos de código para el cifrado del lado del cliente basado en RSA en escenarios de carga y descarga simples, carga multiparte y descarga por rangos.

Nota

El cifrado del lado del cliente basado en KMS solo difiere del basado en RSA en la forma de crear OSSEncryptionClient.

Cifrado basado en RSA: carga y descarga simples

Utilice las CMK para cifrar objetos durante una carga simple y descifrarlos durante una descarga simple:

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();
            }
        }
    }
}

Cifrado basado en RSA: carga multiparte

Utilice un CMK basado en RSA para cifrar objetos durante una carga multiparte:

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();
            }
        }
    }
}

Cifrado basado en RSA: carga reanudable

Utilice un CMK basado en RSA para cifrar objetos durante una carga reanudable:

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();
            }
        }
    }
}

Cifrado basado en RSA: descarga reanudable

Utilice un CMK basado en RSA para descifrar objetos durante una descarga reanudable:

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();
            }
        }
    }
}

Cifrado basado en RSA: descarga por rangos

Utilice un CMK basado en RSA para descifrar objetos durante una descarga por rangos:

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();
            }
        }
    }
}

Referencias

El código de ejemplo completo del cifrado del lado del cliente está disponible en GitHub.