キーを生成してDBに格納する必要があるので、それを文字列に変換しますが、文字列からキーを取得します。これを達成するための可能な方法は何ですか?
私のコードは、
SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);
文字列からキーを取得するにはどうすればよいですか?
キーを生成してDBに格納する必要があるので、それを文字列に変換しますが、文字列からキーを取得します。これを達成するための可能な方法は何ですか?
私のコードは、
SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);
文字列からキーを取得するにはどうすればよいですか?
回答:
をSecretKey
バイト配列(byte[]
)に変換してから、Base64でそれをにエンコードできString
ます。に変換して戻すにはSecretKey
、Base64で文字列をデコードし、それをaで使用しSecretKeySpec
て元のファイルを再構築しますSecretKey
。
文字列へのSecretKey:
// create new key
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// get base64 encoded version of the key
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());
SecretKeyへの文字列:
// decode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// rebuild key using SecretKeySpec
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES");
注I: Base64エンコード/デコード部分をスキップしてbyte[]
、SQLiteに格納するだけです。そうは言っても、Base64エンコード/デコードの実行はコストのかかる操作ではなく、ほとんどすべてのDBに問題なく文字列を格納できます。
注II:以前のJavaバージョンでは、java.lang
またはjava.util
パッケージのいずれかにBase64が含まれていません。ただし、Apache Commons Codec、Bouncy Castle、またはGuavaのコーデックを使用することは可能です。
文字列へのSecretKey:
// CREATE NEW KEY
// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)
SecretKey secretKey;
String stringKey;
try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}
if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}
SecretKeyへの文字列:
// DECODE YOUR BASE64 STRING
// REBUILD KEY USING SecretKeySpec
byte[] encodedKey = Base64.decode(stringKey, Base64.DEFAULT);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
フェイルファストであるいくつかの関数を作成することがどれほど楽しいかを示すために、次の3つの関数を作成しました。
1つはAESキーを作成し、1つはそれをエンコードし、もう1つはデコードして戻します。これらの3つのメソッドは、Java 8で使用できます(内部クラスまたは外部の依存関係なしで)。
public static SecretKey generateAESKey(int keysize)
throws InvalidParameterException {
try {
if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
// this may be an issue if unlimited crypto is not installed
throw new InvalidParameterException("Key size of " + keysize
+ " not supported in this runtime");
}
final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(keysize);
return keyGen.generateKey();
} catch (final NoSuchAlgorithmException e) {
// AES functionality is a requirement for any Java SE runtime
throw new IllegalStateException(
"AES should always be present in a Java SE runtime", e);
}
}
public static SecretKey decodeBase64ToAESKey(final String encodedKey)
throws IllegalArgumentException {
try {
// throws IllegalArgumentException - if src is not in valid Base64
// scheme
final byte[] keyData = Base64.getDecoder().decode(encodedKey);
final int keysize = keyData.length * Byte.SIZE;
// this should be checked by a SecretKeyFactory, but that doesn't exist for AES
switch (keysize) {
case 128:
case 192:
case 256:
break;
default:
throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
}
if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
// this may be an issue if unlimited crypto is not installed
throw new IllegalArgumentException("Key size of " + keysize
+ " not supported in this runtime");
}
// throws IllegalArgumentException - if key is empty
final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
return aesKey;
} catch (final NoSuchAlgorithmException e) {
// AES functionality is a requirement for any Java SE runtime
throw new IllegalStateException(
"AES should always be present in a Java SE runtime", e);
}
}
public static String encodeAESKeyToBase64(final SecretKey aesKey)
throws IllegalArgumentException {
if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {
throw new IllegalArgumentException("Not an AES key");
}
final byte[] keyData = aesKey.getEncoded();
final String encodedKey = Base64.getEncoder().encodeToString(keyData);
return encodedKey;
}
getEncoded()
使用できない他の場所)にある場合、キーの格納/取得が機能しない場合があることに注意してください。
実際、ルイスが提案したことは私にはうまくいきませんでした。私は別の方法を考え出さなければなりませんでした。これは私を助けたものです。あなたも助けるかもしれません。リンク:
* .getEncoded():https ://docs.oracle.com/javase/7/docs/api/java/security/Key.html
エンコーダ情報:https : //docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html
デコーダー情報:https : //docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html
コードスニペット:エンコードの場合:
String temp = new String(Base64.getEncoder().encode(key.getEncoded()));
デコード:
byte[] encodedKey = Base64.getDecoder().decode(temp);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "DES");
使いたくない .toString()
。
SecretKeyはjava.security.Keyから継承され、それ自体がSerializableから継承されていることに注意してください。したがって、ここでのキー(しゃれた意図はありません)は、キーをByteArrayOutputStreamにシリアル化し、byte []配列を取得してそれをdbに格納することです。逆のプロセスは、db []配列をデータベースから取得し、ByteArrayInputStreamを作成して、byte []配列をオフにし、SecretKeyを非直列化します...
...またはもっと簡単に、単に .getEncoded()
java.security.Key(SecretKeyの親インターフェース)から継承されメソッドをます。このメソッドは、Key / SecretKeyからエンコードされたbyte []配列を返します。これは、データベースに格納したり、データベースから取得したりできます。
これはすべて、SecretKey実装がエンコードをサポートしていることを前提としています。さもないと、getEncoded()
nullを返します。
Key / SecretKey javadocs(Googleページの最初にあります)を見てください。
http://download.oracle.com/javase/6/docs/api/java/security/Key.html
またはこれはCodeRanchから(同じGoogle検索でも見つかります):
http://www.coderanch.com/t/429127/java/java/Convertion-between-SecretKey-String-or
StringにSecretKeySpecの変換およびその逆:
あなたは使用することができgetEncoded()
た方法SecretKeySpec
与えるbyteArray
、あなたが使用できることから、encodeToString()
取得することstring
の価値SecretKeySpec
ではBase64
オブジェクトを。
SecretKeySpec
への変換中String
:use decode()
in Base64
will give byteArray
、それからSecretKeySpec
paramsを使用してをインスタンス化し、byteArray
を再現できますSecretKeySpec
。
String mAesKey_string;
SecretKeySpec mAesKey= new SecretKeySpec(secretKey.getEncoded(), "AES");
//SecretKeySpec to String
byte[] byteaes=mAesKey.getEncoded();
mAesKey_string=Base64.encodeToString(byteaes,Base64.NO_WRAP);
//String to SecretKeySpec
byte[] aesByte = Base64.decode(mAesKey_string, Base64.NO_WRAP);
mAesKey= new SecretKeySpec(aesByte, "AES");
これを試してください、それはBase64なしで動作します(これはJDK 1.8にのみ含まれています)、このコードは以前のJavaバージョンでも実行されます:)
private static String SK = "Secret Key in HEX";
// To Encrupt
public static String encrypt( String Message ) throws Exception{
byte[] KeyByte = hexStringToByteArray( SK);
SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");
Cipher c = Cipher.getInstance("DES","SunJCE");
c.init(1, k);
byte mes_encrypted[] = cipher.doFinal(Message.getBytes());
String MessageEncrypted = byteArrayToHexString(mes_encrypted);
return MessageEncrypted;
}
// To Decrypt
public static String decrypt( String MessageEncrypted )throws Exception{
byte[] KeyByte = hexStringToByteArray( SK );
SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");
Cipher dcr = Cipher.getInstance("DES","SunJCE");
dc.init(Cipher.DECRYPT_MODE, k);
byte[] MesByte = hexStringToByteArray( MessageEncrypted );
byte mes_decrypted[] = dcipher.doFinal( MesByte );
String MessageDecrypeted = new String(mes_decrypted);
return MessageDecrypeted;
}
public static String byteArrayToHexString(byte bytes[]){
StringBuffer hexDump = new StringBuffer();
for(int i = 0; i < bytes.length; i++){
if(bytes[i] < 0)
{
hexDump.append(getDoubleHexValue(Integer.toHexString(256 - Math.abs(bytes[i]))).toUpperCase());
}else
{
hexDump.append(getDoubleHexValue(Integer.toHexString(bytes[i])).toUpperCase());
}
return hexDump.toString();
}
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2)
{
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
}
return data;
}
String
キーオブジェクトとバイト配列がクリアされる可能性がある間、Javaでインスタンスを破棄する明示的な方法はありません。これは、キーがメモリ内で長期間利用できることを意味します。(パスワードで保護された)を使用するKeyStore
ことをお勧めします。ランタイムシステム/ OSまたはハードウェアでサポートされているものが望ましいです。