share-image
ESC

Java加密扩展 JCE

使用 RSA 加密上传文件到网易云存储,发现报错

Make sure you have the JCE unlimited strength policy files installed and configured for your JVM

原因是缺少 Java 加密扩展 JCE

解决办法

我的环境是 Java 8 ,可以去这里下载

下载后得到2个 jar 文件

我的环境是 mac 将其拷贝到

/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/security

再次运行程序即可。

网易云 AWS S3 RSA 加密方式上传文件代码

package awsnos.awsnos;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

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.CryptoConfiguration;
import com.amazonaws.services.s3.model.CryptoMode;
import com.amazonaws.services.s3.model.CryptoStorageMode;
import com.amazonaws.services.s3.model.EncryptionMaterials;
import com.amazonaws.services.s3.model.EncryptionMaterialsProvider;
import com.amazonaws.services.s3.model.StaticEncryptionMaterialsProvider;

public class Aws3 {

// loadKeyPair的实现方式,非对称加密algorithm = RSA
public static KeyPair loadKeyPairRSA(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
public static SecretKeySpec loadKeyPairAES(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的方式,非对称加密
public 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的方式,对称加密
public static SecretKey generateCMasterKey() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
KeyGenerator symKeyGenerator = null;
try {
symKeyGenerator = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
symKeyGenerator.init(256);
return symKeyGenerator.generateKey();
}

// 保存Key,该key只要生成一次就好了,要妥善保管,如果该key丢失了,那么意味着通过该key加密的数据将没法解密

// 非对称
public 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();
}

// 对称
public 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();
}

public static void main(String[] args) throws NoSuchAlgorithmException {

String accessKey = "";
String secretKey = "";
String bucketName = "cloud201411";
// 1.生成RSA 密钥对
// try {
// saveKeyPair("/Users/wenjun/Downloads/rsa", genKeyPair("RSA", 1024));
//
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }

// 2.加载 RSA 文件
String keyDir = "/Users/wenjun/Downloads/rsa";
// 1.获取CMK,客户端主密钥,可以使用对称和分对称两种方式,下述使用的是非对称的
KeyPair keyPair = null;
try {
keyPair = loadKeyPairRSA(keyDir, "RSA");
} catch (InvalidKeySpecException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// 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(
"nos-eastchina1.126.net", "us-east-1");
AmazonS3Encryption encryptionClient = AmazonS3EncryptionClientBuilder.standard()
.withCryptoConfiguration(cryptoConfiguration)
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.withEncryptionMaterials(encryptionMaterialsProvider).withClientConfiguration(clientConfiguration)
.withEndpointConfiguration(endpointConfiguration).build();


//要上传文件的路径
String filePath = "tomcat.zip";

try {
encryptionClient.putObject(bucketName,"tomcat11111.zip", new File(filePath));
}catch (Exception e){
System.out.println(e.getMessage());
}
}


}


加密后看到存储有2个文件

一个是 tomcat.zip.instruction,一个是 tomcat.zip

tomcat.zip.instruction 记录着加密文件的元信息


{"x-amz-tag-len":"128","x-amz-iv":"glBQ2qlgTn+8tJkG","x-amz-wrap-alg":"RSA/ECB/OAEPWithSHA-256AndMGF1Padding","x-amz-key-v2":"G/ZrpexIpCaRBHNaU/mBTzAVY61Dm8OlQbvV4EJea2+o4mFcZn2FZ6KXVUb3/qzaYlcol6+nc9gum9J+pNZW1x2tG5RoPJ8e743IOJ9GD7zO5evpUzvk658w4iWbLuaCxTayzha/7VDIBwRiVGClseytCJ2WusadSmFHaIRike4=","x-amz-cek-alg":"AES/GCM/NoPadding","x-amz-matdesc":"{}"}

AES 的加密方式请查看这里

文章作者:阿文
文章链接: https://www.awen.me/post/33176.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿文的博客
本文于 2018-04-10 发布,已超过半年(2851天),请注意甄别内容是否已过期。