|
@@ -0,0 +1,143 @@
|
|
|
|
|
+import com.amazonaws.ClientConfiguration;
|
|
|
|
|
+import com.amazonaws.Protocol;
|
|
|
|
|
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
|
|
|
|
+import com.amazonaws.auth.BasicAWSCredentials;
|
|
|
|
|
+import com.amazonaws.client.builder.AwsClientBuilder;
|
|
|
|
|
+import com.amazonaws.services.s3.AmazonS3Encryption;
|
|
|
|
|
+import com.amazonaws.services.s3.AmazonS3EncryptionClientBuilder;
|
|
|
|
|
+import com.amazonaws.services.s3.model.*;
|
|
|
|
|
+
|
|
|
|
|
+import javax.crypto.KeyGenerator;
|
|
|
|
|
+import javax.crypto.SecretKey;
|
|
|
|
|
+import javax.crypto.spec.SecretKeySpec;
|
|
|
|
|
+import java.io.File;
|
|
|
|
|
+import java.io.FileInputStream;
|
|
|
|
|
+import java.io.FileOutputStream;
|
|
|
|
|
+import java.io.IOException;
|
|
|
|
|
+import java.security.*;
|
|
|
|
|
+import java.security.spec.InvalidKeySpecException;
|
|
|
|
|
+import java.security.spec.PKCS8EncodedKeySpec;
|
|
|
|
|
+import java.security.spec.X509EncodedKeySpec;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @author reghao
|
|
|
|
|
+ * @date 2023-03-21 11:51:45
|
|
|
|
|
+ */
|
|
|
|
|
+public class S3EncTest {
|
|
|
|
|
+ static String region = "chengdu";
|
|
|
|
|
+ static String endpoint = "http://oss-cn-chengdu.reghao.cn/";
|
|
|
|
|
+ static String bucketName = "tnb";
|
|
|
|
|
+ static String accessKey = "your-accesskey";
|
|
|
|
|
+ static String secretKey = "your-secretKey ";
|
|
|
|
|
+ static AmazonS3Encryption s3Client;
|
|
|
|
|
+
|
|
|
|
|
+ static void init() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
|
|
|
|
+ //1.获取CMK,客户端主密钥,可以使用对称和分对称两种方式,下述使用的是非对称的
|
|
|
|
|
+ String keyDir = "/home/reghao/Downloads/key";
|
|
|
|
|
+ KeyPair keyPair = loadRsaKeyPair(keyDir, "RSA");
|
|
|
|
|
+
|
|
|
|
|
+ // 2. Construct an instance of AmazonS3Encryption.
|
|
|
|
|
+ EncryptionMaterials encryptionMaterials = new EncryptionMaterials(keyPair);
|
|
|
|
|
+ ClientConfiguration configuration = new ClientConfiguration();
|
|
|
|
|
+ configuration.setProtocol(Protocol.HTTPS);
|
|
|
|
|
+ CryptoConfiguration cryptoConfiguration = new CryptoConfiguration();
|
|
|
|
|
+ //支持EncryptionOnly,AuthenticatedEncryption,StrictAuthenticatedEncryption,默认是EncryptionOnly,StrictAuthenticatedEncryption不支持range请求
|
|
|
|
|
+ cryptoConfiguration.setCryptoMode(CryptoMode.StrictAuthenticatedEncryption);
|
|
|
|
|
+ //保存加密信息的方式,有两种方式,Instruction模式和Metadata模式,由于NOS分块上传和S3支持上存在一些差异,导致metadata保存的方式大文件下载时由于找不到加密信息而不解密
|
|
|
|
|
+ cryptoConfiguration.setStorageMode(CryptoStorageMode.InstructionFile);
|
|
|
|
|
+ EncryptionMaterialsProvider encryptionMaterialsProvider = new StaticEncryptionMaterialsProvider(encryptionMaterials);
|
|
|
|
|
+
|
|
|
|
|
+ ClientConfiguration clientConfiguration = new ClientConfiguration();
|
|
|
|
|
+ clientConfiguration.setProtocol(Protocol.HTTPS);
|
|
|
|
|
+ AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endpoint, region);
|
|
|
|
|
+ s3Client = AmazonS3EncryptionClientBuilder.standard()
|
|
|
|
|
+ .withCryptoConfiguration(cryptoConfiguration)
|
|
|
|
|
+ .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey,secretKey)))
|
|
|
|
|
+ .withEncryptionMaterials(encryptionMaterialsProvider)
|
|
|
|
|
+ .withClientConfiguration(clientConfiguration)
|
|
|
|
|
+ .withEndpointConfiguration(endpointConfiguration)
|
|
|
|
|
+ .build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //loadKeyPair的实现方式,非对称加密algorithm = RSA
|
|
|
|
|
+ static KeyPair loadRsaKeyPair(String path, String algorithm)
|
|
|
|
|
+ throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
|
|
|
|
|
+ // read public key from file
|
|
|
|
|
+ File filePublicKey = new File(path + "/public.key");
|
|
|
|
|
+ FileInputStream fis = new FileInputStream(filePublicKey);
|
|
|
|
|
+ byte[] encodedPublicKey = new byte[(int) filePublicKey.length()];
|
|
|
|
|
+ fis.read(encodedPublicKey);
|
|
|
|
|
+ fis.close();
|
|
|
|
|
+
|
|
|
|
|
+ // read private key from file
|
|
|
|
|
+ File filePrivateKey = new File(path + "/private.key");
|
|
|
|
|
+ fis = new FileInputStream(filePrivateKey);
|
|
|
|
|
+ byte[] encodedPrivateKey = new byte[(int) filePrivateKey.length()];
|
|
|
|
|
+ fis.read(encodedPrivateKey);
|
|
|
|
|
+ fis.close();
|
|
|
|
|
+
|
|
|
|
|
+ // Convert them into KeyPair
|
|
|
|
|
+ KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
|
|
|
|
+ X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(
|
|
|
|
|
+ encodedPublicKey);
|
|
|
|
|
+ PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
|
|
|
|
|
+
|
|
|
|
|
+ PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(
|
|
|
|
|
+ encodedPrivateKey);
|
|
|
|
|
+ PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);
|
|
|
|
|
+
|
|
|
|
|
+ return new KeyPair(publicKey, privateKey);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //对称加密,algorithm = AES
|
|
|
|
|
+ static SecretKey loadAesKeyPair(String path, String algorithm) throws IOException {
|
|
|
|
|
+ //Read private key from file.
|
|
|
|
|
+ File keyFile = new File(path);
|
|
|
|
|
+ FileInputStream keyfis = new FileInputStream(keyFile);
|
|
|
|
|
+ byte[] encodedPrivateKey = new byte[(int) keyFile.length()];
|
|
|
|
|
+ keyfis.read(encodedPrivateKey);
|
|
|
|
|
+ keyfis.close();
|
|
|
|
|
+ //Generate secret key.
|
|
|
|
|
+ return new SecretKeySpec(encodedPrivateKey, algorithm);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //生成Key的方式,非对称加密
|
|
|
|
|
+ static KeyPair genKeyPair(String algorithm, int bitLength) throws NoSuchAlgorithmException {
|
|
|
|
|
+ KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(algorithm);
|
|
|
|
|
+ SecureRandom srand = new SecureRandom();
|
|
|
|
|
+ keyGenerator.initialize(bitLength, srand);
|
|
|
|
|
+ return keyGenerator.generateKeyPair();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //生成Key的方式,对称加密
|
|
|
|
|
+ static SecretKey generateCMasterKey() throws NoSuchAlgorithmException {
|
|
|
|
|
+ KeyGenerator symKeyGenerator = KeyGenerator.getInstance("AES");
|
|
|
|
|
+ symKeyGenerator.init(256);
|
|
|
|
|
+ return symKeyGenerator.generateKey();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //保存Key,该key只要生成一次就好了,要妥善保管,如果该key丢失了,那么意味着通过该key加密的数据将没法解密
|
|
|
|
|
+ //非对称
|
|
|
|
|
+ static void saveKeyPair(String dir, KeyPair keyPair) throws IOException {
|
|
|
|
|
+ PrivateKey privateKey = keyPair.getPrivate();
|
|
|
|
|
+ PublicKey publicKey = keyPair.getPublic();
|
|
|
|
|
+
|
|
|
|
|
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey.getEncoded());
|
|
|
|
|
+ FileOutputStream fos = new FileOutputStream(dir + "/public.key");
|
|
|
|
|
+ fos.write(x509EncodedKeySpec.getEncoded());
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+
|
|
|
|
|
+ PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateKey.getEncoded());
|
|
|
|
|
+ fos = new FileOutputStream(dir + "/private.key");
|
|
|
|
|
+ fos.write(pkcs8EncodedKeySpec.getEncoded());
|
|
|
|
|
+ fos.close();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //对称
|
|
|
|
|
+ static void saveSymmetricKey(String path, SecretKey secretKey) throws IOException {
|
|
|
|
|
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(secretKey.getEncoded());
|
|
|
|
|
+ FileOutputStream keyfos = new FileOutputStream(path);
|
|
|
|
|
+ keyfos.write(x509EncodedKeySpec.getEncoded());
|
|
|
|
|
+ keyfos.close();
|
|
|
|
|
+ }
|
|
|
|
|
+}
|