![](/img/trans.png)
[英]NoSuchAlghoritmExeption when you call the java cipher.getinstance()
[英]What is the algorithm string for 'AGCM256-KW' in java cryptography, to be used in Cipher.getInstance(String algo)?
參考這個 ,我必須使用算法AGCM256-KW加密。 我正在使用Java Cryptography,我沒有找到任何這樣的算法。 我發現最接近的是AES_256 / GCM / NoPadding,但它沒有KW(密鑰包裝)。
這是我的測試代碼
public void testEncryption(String algo) {
String shared_secret = "LyQnklSrxsk3Ch2+AHi9HoDW@//x1LwM123QP/ln";
try {
// Step 1 - Create SHA-256 digest of the shared key
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(shared_secret.getBytes("UTF-8"));
// Step 2 - generate a 256 bit Content Encryption Key(CEK)
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(256);
SecretKey cek = kg.generateKey();
// Step 3 - encrypt the CEK using 256 bit digest generated in Step 1
// and 96 bit random IV. Algorithm should be
// random 96 bit Initialize Vector
SecureRandom random = new SecureRandom();
// byte iv[] = new byte[96];
// random.nextBytes(iv);
byte iv[] = random.generateSeed(96);
System.out.println("IV: " + toBase64(iv) + " length: " + iv.length);
IvParameterSpec ivspec = new IvParameterSpec(iv);
GCMParameterSpec gspec = new GCMParameterSpec(96, iv);
// encrypt
Cipher cipher = Cipher.getInstance(algo);
System.out.println(String.format("CEK Cipher alg:%S provider:%S", cipher.getAlgorithm(),
cipher.getProvider().getName()));
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(digest, "AES"), gspec);
byte[] result = cipher.doFinal(cek.getEncoded());
System.out.println(String.format("Encrypted CEK :%S", toBase64(result)));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
是的,Visa令牌服務似乎使用JWE(現在是RFC 7516 ),因此您可以使用jose4j。 下面是一些示例代碼,顯示使用A256GCMKW和AGCM256使用JWE加密和解密某些內容:
// shared secret hashed to key from your example
String shared_secret = "LyQnklSrxsk3Ch2+AHi9HoDW@//x1LwM123QP/ln";
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(shared_secret.getBytes("UTF-8"));
JsonWebEncryption jwe = new JsonWebEncryption();
// A256GCMKW for key wrap
jwe.setAlgorithmHeaderValue(KeyManagementAlgorithmIdentifiers.A256GCMKW);
// A256GCM for content encryption
jwe.setEncryptionMethodHeaderParameter(ContentEncryptionAlgorithmIdentifiers.AES_256_GCM);
// the key (from above)
jwe.setKey(new SecretKeySpec(digest, "AES"));
// whatever content you want to encrypt
jwe.setPayload("some important content to be encrypted and integrity protected");
// Produce the JWE compact serialization, which is where the actual encryption is done.
// The JWE compact serialization consists of five base64url encoded parts
// combined with a dot ('.') character in the general format of
// <header>.<encrypted key>.<initialization vector>.<ciphertext>.<authentication tag>
String serializedJwe = jwe.getCompactSerialization();
// Do something with the JWE. Like send it to some other party over the clouds
// and through the interwebs.
System.out.println("JWE compact serialization: " + serializedJwe);
// That other party, the receiver, can then use JsonWebEncryption to decrypt the message.
JsonWebEncryption receiverJwe = new JsonWebEncryption();
// Set the compact serialization on new Json Web Encryption object
receiverJwe.setCompactSerialization(serializedJwe);
// Symmetric encryption, like we are doing here, requires that both parties have the same key.
// The key will have had to have been securely exchanged out-of-band somehow.
receiverJwe.setKey(new SecretKeySpec(digest, "AES"));
// Get the message that was encrypted in the JWE. This step performs the actual decryption steps.
String plaintext = receiverJwe.getPlaintextString();
// And do whatever you need to do with the clear text message.
System.out.println("plaintext: " + plaintext);
假設您確實在GCM模式下確實需要AES(我從未聽說過AGCM,但我想這是一個邏輯假設,它意味着AES / GCM)。 然后,以下內容可用於(un)包裝密鑰。 請注意,我沒有使用IvParameterSpec
,至少不適用於Oracle JCE。
SecretKey sk = new SecretKeySpec(new byte[16], "AES");
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec gcmSpec = new GCMParameterSpec(128, new byte[12]);
cipher.init(Cipher.WRAP_MODE, sk, gcmSpec);
byte[] wrappedKey = cipher.wrap(sk);
System.out.println(Hex.toHexString(wrappedKey));
cipher.init(Cipher.UNWRAP_MODE, sk, gcmSpec);
SecretKey unwrap = (SecretKey) cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
System.out.println(Hex.toHexString(unwrap.getEncoded()));
請注意,對於包裝密鑰,使用SIV模式可能有點優先,因為您不需要將IV 和身份驗證標記與包裝密鑰一起存儲(存儲IV未在示例中顯示)。 上面的代碼依賴於唯一的IV安全性(也未示出)。
顯然,用自己包裝一個密鑰也不是一個好主意。 對不起,我這里有點懶; 我剛剛展示了如何使用密碼。
“KW”指的是“密鑰包裝”,如RFC 3394中所定義.JCE中該算法的名稱是“AESWrap”。 因此,轉換應該是“AESWrap / GCM / NoPadding”。 正如Maarten指出的那樣,邏輯上這個操作應該在WRAP_MODE
配置Cipher
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.