1.はじめに
暗号化の方法は、ただ1つのキー、非対称暗号化は2つのキーを持っていることを除いて、対称暗号化、対称暗号化と非対称暗号化に分かれています
- 対称暗号化と復号化:enccrypt(プレーンテキスト、キー)=暗号文解読(暗号文、キー)=平文
- 非対称暗号化:暗号化(平文、公開鍵)=暗号文解読(暗号文、秘密鍵)=平文
2.キー
2.1。キーの形式
2.1.1.the
.DERキー、JAVAで符号化されたバイナリのストリームとして読み取られるキー。ここでは、公開鍵を取得する例を示します。
/**
* der公钥解密,密文Base64输出
*/
public static PublicKey getPublicKeyByDer(InputStream is) throws Exception {
try {
if (certificatefactory == null) {
certificatefactory = CertificateFactory.getInstance("X.509");
}
Certificate cert = certificatefactory.generateCertificate(is);
return cert.getPublicKey();
}finally {
if (is != null) {
is.close();
}
}
}
2.1.2.pem
.PEMは、 "----- BEGIN ..." に冒頭で、 "----- END ..." 最後に、コンテンツは、BASE64エンコーディングです。ここでは、公開鍵を取得する例を示します。
public static PublicKey getPublicKeyByPem(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(publicKey));
return keyFactory.generatePublic(keySpec);
}
2.1.3.PKCS12
.p12PKCS#12証明書は、簡単に言えば、それは証明書と秘密鍵が含まれており、パスワード保護することができます。ここでは、秘密鍵を取得する例を示します。
public static Key getP12Key() throws Exception{
try (InputStream is = new FileInputStream( "xx.p12")) {
if (certificatefactory == null) {
certificatefactory = CertificateFactory.getInstance("X.509");
}
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(is, "p12证书的密码".toCharArray());
Key key = keystore.getKey("p12证书的别名", "p12证书的密码".toCharArray());
key.getAlgorithm();//密钥对应的加密算法,可以用在 Cipher.getInstance(key.getAlgorithm())
return key;
}
}
2.1.4。ピュア文字列
キーは、文字列またはBase64でエンコード、あるいは直接文字列に、キーはバイト[]キーを生成することができる変換する方法を見つけることであるコーディング進数であってもよいです。
RSA鍵は、このようにして得ることができます。
public static PublicKey getRSAPublicKey(byte[] publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
return keyFactory.generatePublic(keySpec);
}
AESキーは、このようにして得ることができます。
public static Key getKey(byte[] key) throws Exception {
return new SecretKeySpec(key, "AES");
}
2.2。タイプ
X509EncodedKey
PKCS8EncodedKey
RSAPublicKey
RSAPrivateKey
DSAPublicKey
DSAPrivateKeyインタフェース
2.3。長さ
- 128ビット
- AESの256ビットJAVAキーの長さが限界、128ビットの最大値、すなわち、16ビットのビット列を有しています。キーは256ビットである場合、暗号化と復号化の、すなわち32ビットのビット列は、JREまたはCryptoJS AES方式の文書を使用して変更することができます。
2.4。キーの暗号化
- PBKDF2WithHmacSHA1PBKDF2(パスワードベースのキー派生関数)は、一般的に暗号化されたパスワードを形成するために用いられる鍵を導出するために使用される機能です。その基本原理は、擬似ランダム関数(例えばHMAC関数)、および入力パラメータとして塩値平文で、操作を繰り返し、最後にキーを生成しています。繰り返しの回数は、コストが高くなる壊すのに十分な大きさである場合。そして、「虹のテーブル」攻撃の難易度が増加しますsalt値を追加します。
以下は、JAVA PBKDF2WithHmacSHA1を実現しています
private static final String DEFAULT_ALGORITHM = "PBKDF2WithHmacSHA1";
private static final int DEFAULT_ITERATIONS = 10000;
private static final int DEFAULT_HASH_SIZE = 128;
private static final byte[] DEFAULT_SALT = new byte[]{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
public static byte[] hash(String key) throws Exception {
char[] password = key.toCharArray();
return hash(password, DEFAULT_ALGORITHM, DEFAULT_ITERATIONS, DEFAULT_HASH_SIZE, DEFAULT_SALT);
}
/**
* @param password 密钥
* @param algorithm 运算算法
* @param iteration 进行重复计算的次数
* @param hashSize 期望得到的密钥的长度
* @param salt 盐值
* @return 最后生成的密钥
* @throws Exception 各种异常
*/
public static byte[] hash(char[] password, String algorithm, int iteration, int hashSize, byte[] salt) throws Exception {
SecretKeyFactory skf = SecretKeyFactory.getInstance(algorithm);
PBEKeySpec spec = new PBEKeySpec(password, salt, iteration, hashSize);
return skf.generateSecret(spec).getEncoded();
}
3.暗号化アルゴリズム
3.1対称
3.1.1.DES
DESは、共通の一種内部対称暗号化され、データ暗号化規格、ブロック鍵暗号化アルゴリズム、すなわち、データ暗号化規格と呼びます。鍵長が64ビット(ビット)であり、鍵の長さは無視さ超えます。いわゆる対称暗号、同じ暗号化と復号化鍵。対称暗号化は、一般的に固定長文字列はブロックに暗号化します。単一の部品またはちょうど最後の特殊パディング文字の欠如。クロスランゲージは、多くの場合、問題が発生し、多くの場合、DESの暗号化と復号化を行います。しばしば間違った方法で充填された、または矛盾コーディング、又は選択結果(ECB、CBC、CTR、OFB、CFB、NCFB、nofbを)は対応する暗号化と復号化モードです。'PKCS5'、 'PKCS7'、 'iso10126'、 'ansix923'、DES-ECB、DES-CBC、DES-CTR、DES-OFB、DES-CFBを含む 'ゼロ' タイプ、共通パターンで充填
public static byte[] desEncrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("DES");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "DES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
3.1.2.3DES
(また、トリプルDESとも呼ばれる)3DESは総称トリプルデータ暗号化アルゴリズム(TDEA、トリプルデータ暗号化アルゴリズム)ブロック暗号です。これは、トリプルDES暗号化アルゴリズムは、各データ・ブロックに適用されるに相当します。パスワードは、ビットの数は、同じDES暗号化結果64に等しい未満である場合にキーの長さは、128ビット、192(「ビット)です。簡単にオリジナルDES、新しい、増加した暗号化セキュリティの3DESの出現をクラックするために、ブルートフォースを避けます。また、対称暗号化され、同一の暗号化は、符号化、および充填モードを含みます。含む3DES-ECB、3DES-CBC、3DES-CTR、3DES-OFB、3DES-CFB
public static byte[] desedeEncrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("DESede");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "DESede");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
3.1.3。AES
AES、高度暗号化標準(英語:高度暗号化規格、略称:AES)は、また、ラインダール暗号化方式として知られている暗号化方式で、米国連邦政府によって採用されたブロック暗号化規格です。この規格は、オリジナルのDESを置き換えるために使用されることは広く分析されており、世界中で使用マルチ。AESの固定ブロック長:厳密(二つが実用的なアプリケーションで互換的に使用されてもよい)、AESラインダール暗号化方法、および正確に同じではないに言えば、ラインダール暗号方法および鍵ブロックので、長さの広い範囲をサポートすることができます128ビットは、キーの長さは128、192または256ビットであってもよく、ラインダールブロック長および鍵と256ビットの上限下限として128に、32の整数倍で使用することができます。AES-ECB、AES-CBC、AES-CTR、AES-OFB、AES-CFBを含みます
public static byte[] aesEncrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
AESアルゴリズムモードとパディングいくつかのオプションがありますが、ECBとCBCは相殺される必要はありませんオフセット。バイト配列あれば、例えば、そしてPKCS7Padding PKCS5Paddingほぼ同じで、ジェネリックであり得る、スタッフィングバイトのコンテンツ長配列で満たさ; NoPaddingは満たされていない、この時間は、手動で暗号化またはバイト数は16の倍数であることを確認するコンテンツ復号あります1つのバイト配列の長さは、15 0xFのを充填する必要がある場合は、長さ15は、一方のみが、その後は0x1で満たされ、16まで充填する必要がある。ZeroPaddingが0x0ので満たされます。
Cipher.getInstance("AES/CBC/NoPadding");
Cipher.getInstance("AES/CBC/PKCS5Padding");
Cipher.getInstance("AES/CBC/PKCS7Padding");
Cipher.getInstance("AES/CBC/ZeroBytePadding");
Cipher.getInstance("AES/ECB/NoPadding");
Cipher.getInstance("AES/ECB/PKCS5Padding");
Cipher.getInstance("AES/ECB/PKCS7Padding");
Cipher.getInstance("AES/ECB/ZeroBytePadding");
さらに、AESの鍵長は、それぞれの文字列16、24、32の長さに対応し、128バイト、192byte、256バイトです。不正なキーサイズまたはデフォルトパラメータ:キーは128バイト、すなわち、16ビットの文字列の長さよりも大きい場合、コードはjava.security.InvalidKeyExceptionをスローします。不正なキーサイズまたはデフォルトパラメータが制限され、Javaランタイム環境ポリシーファイルを制限されて読まれるキーの長さを参照してください。ファイルは$ {JAVA_HOME} / JRE / libに/セキュリティに位置する米国は、ソフトウェアの輸出を制御しているため、この制限があります。解決策は2つあります
- 替换${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar。
- 使用CryptoJs,这是谷歌开源的用Js实现的AES加解密库,速度和原生JDK相差无几,除了第一次载入Js文件需要额外耗时。
3.1.4.RC4
RC4暗号化アルゴリズムは、1987設計変数ストリーム暗号アルゴリズムクラスタのロナルド・リベスト、キーの長さでトップの男のRSAトリオです。アルゴリズムの速度は10倍DES暗号化に到達し、非線形の非常に高いレベルを持つことができます。1994年9月には、そのアルゴリズムは、インターネットに掲載されました。暗号化アルゴリズムRC4のXORを使用しているので、サブキー反復配列が発生すると、暗号文が割れする可能性があるように。ハッカーの攻撃に対して脆弱古いRC4認証および暗号化アルゴリズムとして、それは今、ますます使用は推奨されませんされています。
public static byte[] rc4Encrypt(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance("RC4");
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "ARCFOUR");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
return cipher.doFinal(data);
}
3.2。非対称
3.2.1。RSA
暗号化と復号鍵が異なっている、秘密鍵は、一般的に、秘密鍵暗号を使用して、復号化するために公開鍵暗号や秘密鍵を使用して、開示されていない、公開鍵を解読することができます。そして、AESは異なる、結果のうち、各暗号化は同じではありません。そして、必要性が117バイト長までの各グループをRSAは、暗号化し、パケットの暗号化を行うために、最大128の各グループは、バイト長を復号化します。
public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
PublicKey key = keyFactory.generatePublic(keySpec);
cipher.init(Cipher.ENCRYPT_MODE, key);
//执行分组加密操作,RSA加密每一组最多117位长度
int segment = 117;
int inputLen = data.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > segment) {
cache = cipher.doFinal(data, offSet, segment);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * segment;
}
return out.toByteArray();
}
}
public static byte[] encryptByPrivateKey(byte[] data, byte[] publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
PrivateKey key = keyFactory.generatePrivate(keySpec);
cipher.init(Cipher.ENCRYPT_MODE, key);
//执行分组加密操作,RSA加密每一组最多117位长度
int segment = 117;
int inputLen = data.length;
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加密
while (inputLen - offSet > 0) {
if (inputLen - offSet > segment) {
cache = cipher.doFinal(data, offSet, segment);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * segment;
}
return out.toByteArray();
}
}
3.3補足追加のアルゴリズム
BouncyCastleを頼り追加し、プログラムの初期化時に一度呼び出さ
Security.addProvider(new BouncyCastleProvider());
あなたはより多くの暗号化アルゴリズムCipher.getInstance(「」)メソッドを得ることができます。
4.署名
4.1。アルゴリズム
4.1.1.SHA1withRSA
/**
* RSA签名
*
* @param content 待签名数据
* @param privateKey 商户私钥
* @param encode 字符集编码
* @return 使用Base64编码的签名值
*/
public static String sign(String content, String privateKey, String encode) throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, UnsupportedEncodingException, SignatureException {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
java.security.Signature signature = java.security.Signature.getInstance("SHA256withRSA");
signature.initSign(priKey);
signature.update(content.getBytes());
byte[] signed = signature.sign();
return Base64.encode(signed);
}
4.1.2。残りの共通の秘密鍵署名
/**
* 私钥签名底层操作
*
* @param algorithm NONEwithRSA
* MD2withRSA,MD5withRSA
* SHA1withRSA,SHA256withRSA ,SHA384withRSA ,SHA512withRSA
* NONEwithDSA
* SHA1withDSA
* NONEwithECDSA ,SHA1withECDSA ,SHA256withECDSA ,SHA384withECDSA ,SHA512withECDSA
* @param data byte[]
* @param privateKey PrivateKey
* @return byte[]
*/
public static byte[] sign(String algorithm, byte[] data, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance(algorithm);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
5.ハッシュ
- SHA1
- SHA256
- SHA384
- SHA512
- MD2
- MD5
apacheの-コモンズ・コーデックはDigestUtilsが完全に達成しています。
参考資料
https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html文書様々な暗号化アルゴリズムは、公式のJavaの名前で実装します
https://www.example-code.com/java/rsa.asp RSA例
https://www.programcreek.com/java-api-examples/アルゴリズムとキーデモの様々を見つけます
http://tool.chacuo.net/cryptaes暗号化アルゴリズムウェブサイトの正当性を確認します