blog

公式:一般的な暗号化アルゴリズムについて教えて。

暗号化アルゴリズムは全体として、可逆暗号化と不可逆暗号化に分けることができ、可逆暗号化は対称暗号化と非対称暗号化に分けることができます。 一般的な不可逆暗号化アルゴリズムには、MD5、HMAC、SHA...

Apr 5, 2020 · 10 min. read
シェア

暗号化アルゴリズムは全体として、可逆暗号化と不可逆暗号化に分けられ、可逆暗号化は対称暗号化と非対称暗号化に分けられます。

不可逆暗号化

一般的な不可逆暗号化アルゴリズムには、MD5、HMAC、SHA1、SHA-422、SHA-652、SHA-483、SHA-215があり、このうちSHA-422、SHA-652、SHA-483、SHA-215を総称してSHA2暗号化アルゴリズムと呼ぶことができます。暗号化アルゴリズムはSHA1よりもセキュリティレベルが高いです。SHAに続く数字は暗号化された文字列の長さを示し、SHA1はデフォルトで1ビットのメッセージダイジェストを生成します。

不可逆暗号化アルゴリズムの最大の特徴は鍵ですが、HMACは鍵を必要とする手動のドッグヘッドです。

これらの暗号化は不可逆であるため、より一般的なシナリオはユーザーパスワードの暗号化であり、検証プロセスは2つの暗号化された文字列が同じかどうかを比較することによって身元を確認することです。また、MD5パスワードをクラックすることができると主張する多くのオンラインウェブサイトがあり、原理は同じです、つまり、多くの文字列と対応するMD5暗号化文字列の巨大なリポジトリがあり、比較するために入力するMD5暗号化文字列を介して、あなたのパスワードの複雑さが比較的低い場合は、まだ検証アウトの高い確率があります。

MD5

MD5メッセージ・ダイジェスト・アルゴリズムは、広く使われている暗号ハッシュ関数で、メッセージが完全かつ一貫して送信されることを保証するために使用される128ビットのハッシュ値を生成します。

MD5アルゴリズムには次のような特徴があります:

1、圧縮:関係なく、データの長さはどのくらいですが、計算されたMD5の値の長さは同じです。

2、計算が簡単:元のデータからMD5値を計算するのが簡単です。

3、修正への耐性:たとえ1バイトの修正であっても、計算されたMD5の値は大きな違いになります。

4、衝突抵抗:データとMD5の値を知って、同じ元のデータの同じMD5の値を見つける確率は非常に小さい。

public static String md5(String text) {
 MessageDigest messageDigest = null;
 try {
 messageDigest = MessageDigest.getInstance("MD5");
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 byte[] bytes = messageDigest.digest(text.getBytes());
 return Hex.encodeHexString(bytes); 
}

SHA

セキュアハッシュアルゴリズムは、FIPS認定のセキュアハッシュアルゴリズムである暗号化ハッシュ関数のファミリーです。数値メッセージに対応する固定長の文字列を計算するアルゴリズムです。入力メッセージが異なる場合、それらが異なる文字列に対応する確率は高くなります。

2005年8月17日に開催されたCRYPTOカンファレンスの最後に、Xiaoyun Wang、Zhizhi Yao、Cufeng Yaoは、計算量の2の63乗以内で衝突を見つけることができる、より効率的なSHA-1攻撃方法を再び発表しました。

つまり、SHA-1暗号化アルゴリズムには、小さいとはいえ衝突の可能性があるということです。

public static String sha256(String text) {
 MessageDigest messageDigest = null;
 try {
 messageDigest = MessageDigest.getInstance("SHA-256");
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 byte[] bytes = messageDigest.digest(text.getBytes()); 
 return Hex.encodeHexString(bytes); 
}

HMAC

HMACは、Key Related Hash Arithmetic Message Authentication Codeの略で、ハッシュ関数と鍵に基づくメッセージ認証の方法として1996年にH. Krawezyk、M. Bellare、R. Canettiによって提案され、1997年にRFC2104として公開され、IPSecはじめとするネットワークプロトコルで広く利用され、現在ではインターネットセキュリティのデファクトスタンダードとなっています。は事実上のインターネットセキュリティ標準となっています。任意の反復ハッシュ関数とバンドルすることができます。

HMACアルゴリズムは、暗号アルゴリズムというよりも、セキュリティが使用されるハッシュ・アルゴリズムに完全に依存しないキーを導入するものです。

public static String hmacSha256(String text, SecretKeySpec sk) {
 Mac mac = null;
 try {
 mac = Mac.getInstance("HmacSHA256");
 } catch (NoSuchAlgorithmException e) {
 e.printStackTrace();
 }
 try {
 mac.init(sk);
 } catch (InvalidKeyException e) {
 e.printStackTrace();
 }
 byte[] rawHmac = mac.doFinal(text.getBytes());
 return new String(Base64.encodeBase64(rawHmac));
}

不可逆暗号化では、SHA256、SHA384、SHA512、およびHMAC-SHA256、HMAC-SHA384、HMAC-SHA512が推奨アルゴリズムです。

対称暗号化アルゴリズム

対称暗号化アルゴリズムは、データの暗号化と復号化の両方に同じ鍵を使用する比較的初期のアプリケーションアルゴリズムです。一般的な対称暗号化アルゴリズムは、DES、3DES、AES821、AES291、AES652 です。AES の後の数字は鍵の長さを表します。対称暗号化アルゴリズムは比較的セキュリティが低いため、イントラネット環境での暗号化と復号化に適しています。

DES

DESは対称暗号化アルゴリズムの代表的なアルゴリズムで、デフォルトの鍵長はビットです。

//  
public static String encrypt(byte[] dataSource, String password){
 try {
 SecureRandom random = new SecureRandom();
 DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
 //キーファクトリを作成し、それを使ってDESKeySpecを
 SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); 
 SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec); 
 //Cipherオブジェクトは実際に暗号化操作を完了する
 Cipher cipher = Cipher.getInstance("DES"); 
 //キーでサイファーオブジェクトを初期化する
 cipher.init(Cipher.ENCRYPT_MODE, secretKey, random); 
 //暗号化操作の正式な実行
 return Base64.encodeBase64String(cipher.doFinal(dataSource)); 
 } catch (Throwable e) { 
 e.printStackTrace(); 
 } return null; 
 } 
//  
public static String decrypt(String src, String password) throws Exception{ 
 // DESアルゴリズムには、信頼できる乱数源が必要である。
 SecureRandom random = new SecureRandom(); 
 // DESKeySpecオブジェクトを作成する。
 DESKeySpec desKeySpec = new DESKeySpec(password.getBytes()); 
 // 鍵ファクトリーを作成する
 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 
 // DESKeySpecオブジェクトをSecretKeyオブジェクトに変換する。
 SecretKey secretKey = keyFactory.generateSecret(desKeySpec); 
 // Cipherオブジェクトは実際に復号化操作を完了する
 Cipher cipher = Cipher.getInstance("DES"); 
 // キーでサイファーオブジェクトを初期化する
 cipher.init(Cipher.DECRYPT_MODE, secretKey, random); 
 // 復号化操作が本当に始まる
 return new String(cipher.doFinal(Base64.decodeBase64(src))); 
}

3DES

public static String encryptThreeDESECB(String src, String key) {
 try{
 DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
 SecretKey securekey = keyFactory.generateSecret(dks);
 Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
 cipher.init(Cipher.ENCRYPT_MODE, securekey);
 byte[] b = cipher.doFinal(src.getBytes("UTF-8"));
 String ss = new String(Base64.encodeBase64(b));
 ss = ss.replaceAll("\+", "-");
 ss = ss.replaceAll("/", "_");
 return ss;
 } catch(Exception ex){
 ex.printStackTrace();
 return src;
 }
}
public static String decryptThreeDESECB(String src, String key) {
 try{
 src = src.replaceAll("-", "+");
 src = src.replaceAll("_", "/");
 byte[] bytesrc = Base64.decodeBase64(src.getBytes("UTF-8"));
 // --鍵の復号化
 DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
 SecretKey securekey = keyFactory.generateSecret(dks);
 // --Chipherオブジェクトの復号化
 Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
 cipher.init(Cipher.DECRYPT_MODE, securekey);
 byte[] retByte = cipher.doFinal(bytesrc);
 return new String(retByte, "UTF-8");
 } catch(Exception ex){
 ex.printStackTrace();
 return src;
 }
}

AES

AES Advanced Data Encryption Standard(AES)は、DESアルゴリズムに対する既知の攻撃すべてに有効で、デフォルトの鍵長はbit、オプションでbit, bitがあります。デフォルトの鍵長はbitで、オプションでbit, bitもあります。 ちなみにこのbitはビットのことです。

private static final String defaultCharset = "UTF-8";
private static final String KEY_AES = "AES";
private static final String KEY_MD5 = "MD5";
private static MessageDigest md5Digest;
static {
 try {
 md5Digest = MessageDigest.getInstance(KEY_MD5);
 } catch (NoSuchAlgorithmException e) {
 }
}
/**
 *  
 */
public static String encrypt(String data, String key) {
 return doAES(data, key, Cipher.ENCRYPT_MODE);
}
/**
 *  
 */
public static String decrypt(String data, String key) {
 return doAES(data, key, Cipher.DECRYPT_MODE);
}
/**
 *  
 */
private static String doAES(String data, String key, int mode) {
 try {
 boolean encrypt = mode == Cipher.ENCRYPT_MODE;
 byte[] content;
 if (encrypt) {
 content = data.getBytes(defaultCharset);
 } else {
 content = Base64.decodeBase64(data.getBytes());
 }
 SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset))
 , KEY_AES);
 Cipher cipher = Cipher.getInstance(KEY_AES);// 暗号を作成する
 cipher.init(mode, keySpec);//  
 byte[] result = cipher.doFinal(content);
 if (encrypt) {
 return new String(Base64.encodeBase64(result));
 } else {
 return new String(result, defaultCharset);
 }
 } catch (Exception e) {
 }
 return null;
}

推奨される対称暗号化アルゴリズムはAES821、AES291、AES652です。

非対称暗号化アルゴリズム

非対称暗号化アルゴリズムは、全く異なるが完全に一致する2つの鍵を持っています。平文の暗号化と復号のプロセスは、公開鍵と秘密鍵のペアを一致させて初めて完了します。一般的な非対称暗号化には、RSA や SM2 などがあります。

RSA

RSA鍵は少なくとも500ビット、一般的には1024ビットが推奨されています。

//非対称鍵アルゴリズム
public static final String KEY_ALGORITHM = "RSA";
/**
 * DHアルゴリズムのデフォルトの鍵長は1024である。
 * 鍵長は64の倍数、512ビットから65536ビットでなければならない。
 */
private static final int KEY_SIZE = 1024;
// 
private static final String PUBLIC_KEY = "RSAPublicKey";
// 
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
 * 鍵ペアを初期化する
 *
 * @return Map Aキーのマップ
 */
public static Map<String, Object> initKey() throws Exception {
 //インスタンス化された鍵生成器
 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
 //鍵生成器を初期化する
 keyPairGenerator.initialize(KEY_SIZE);
 //鍵ペアの生成
 KeyPair keyPair = keyPairGenerator.generateKeyPair();
 //公開鍵
 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 //当事者Aの秘密鍵
 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 //鍵をマップに保存する
 Map<String, Object> keyMap = new HashMap<String, Object>();
 keyMap.put(PUBLIC_KEY, publicKey);
 keyMap.put(PRIVATE_KEY, privateKey);
 return keyMap;
}
/**
 * 秘密鍵暗号化
 *
 * @param data 暗号化するデータ
 * @param key  
 * @return byte[] 暗号化データ
 */
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {
 //秘密鍵を入手する
 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 //秘密鍵を生成する
 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 //データ暗号化
 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 return cipher.doFinal(data);
}
/**
 * 公開鍵暗号化
 *
 * @param data 暗号化するデータ
 * @param key  
 * @return byte[] 暗号化データ
 */
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {
 //インスタンス化されたキーファクトリ
 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 //公開鍵を初期化する
 //鍵素材の変換
 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
 //公開鍵を生成する
 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 //データ暗号化
 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 cipher.init(Cipher.ENCRYPT_MODE, pubKey);
 return cipher.doFinal(data);
}
/**
 * 秘密鍵の復号化
 *
 * @param data 復号化するデータ
 * @param key  
 * @return byte[] 復号化されたデータ
 */
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
 //秘密鍵を入手する
 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 //秘密鍵を生成する
 PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 //データの復号化
 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 cipher.init(Cipher.DECRYPT_MODE, privateKey);
 return cipher.doFinal(data);
}
/**
 * 公開鍵復号化
 *
 * @param data 復号化するデータ
 * @param key  
 * @return byte[] 復号化されたデータ
 */
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {
 //インスタンス化されたキーファクトリ
 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
 //公開鍵を初期化する
 //鍵素材の変換
 X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
 //公開鍵を生成する
 PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
 //データの復号化
 Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 cipher.init(Cipher.DECRYPT_MODE, pubKey);
 return cipher.doFinal(data);
}
/**
 * 秘密鍵を入手する
 *
 * @param keyMap キーマップ
 * @return byte[]  
 */
public static byte[] getPrivateKey(Map<String, Object> keyMap) {
 Key key = (Key) keyMap.get(PRIVATE_KEY);
 return key.getEncoded();
}
/**
 * 公開鍵を入手する
 *
 * @param keyMap キーマップ
 * @return byte[]  
 */
public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
 Key key = (Key) keyMap.get(PUBLIC_KEY);
 return key.getEncoded();
}

暗号化ソルト

暗号化ソルトも、より一般的に聞かれる概念であり、ソルトは暗号化文字列の暗号化に使用されるランダムな文字列と暗号化のスプライシングです。ソルトは、主に暗号化された文字列のセキュリティを提供することです。塩が暗号化された文字列がある場合、ハッカーは、この暗号化された文字列の特定の手段を介して、彼は文字列の暗号化ではなく、平文を得たが、文字列の暗号化と文字列の塩の組み合わせの前に、相対的に言えば、文字列のセキュリティも向上しました。

本文中のいくつかのアルゴリズムはウェブから得たもので、そのままコピーして使用することができます

推奨される暗号化アルゴリズムは以下の通りです:

  • 不可逆暗号化:SHA652、SHA483、SHA215、HMAC-SHA652、HMAC-SHA483、HMAC-SHA512
  • 対称暗号化アルゴリズム:AES、3DES
  • 非対称暗号化アルゴリズム:RSA

Read next

AndroidのSurfaceTextureについて語ろう!

SurfaceTextureはAndroidでレンダリングするためのコアコンポーネントで、SurfaceとOpenGL ESテクスチャを組み合わせたもので、GLESテクスチャSurfaceに出力を提供するために使用されます。Androidレンダリングシステムから見ると、それはコンシューマであり、プロデューサは新しいイージングになります。

Apr 5, 2020 · 11 min read