分别使用椭圆曲线密码学对短信进行加解密
Encryption and Decryption of text messages using Elliptic Curve Cryptography Separately
我有这段代码可以同时使用椭圆曲线密码术加密和解密文本消息。我把代码分成两部分:加密和解密。但是在解密过程中我得到了错误。谁能帮我解决一下。
共享代码:
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Scanner;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Enumeration;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class ENCRYPT {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
System.out.println("IV :" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Message:");
String plainText = sc.nextLine();
System.out.println("Original plaintext message: " + plainText);
// Initialize two key pairs
KeyPair keyPairA = generateECKeys();
KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
keyPairB.getPublic());
SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
String cipherText = encryptString(secretKeyA, plainText);
System.out.println("Encrypted cipher text: " + cipherText);
String encodedKeyA = Base64.getEncoder().encodeToString(secretKeyA.getEncoded());
String encodedKeyB = Base64.getEncoder().encodeToString(secretKeyB.getEncoded());
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println("Secret Key A: " + encodedKeyA);
System.out.println("Secret Key B: " + encodedKeyB);
}
public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException |
NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static String encryptString(SecretKey key, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
UnsupportedEncodingException | ShortBufferException |
IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
public static String decryptString(SecretKey key, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(key.getEncoded(),
key.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength += cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
解密密码:
//Decrypt
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class Decrypt {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
/* Scanner scc = new Scanner(System.in);
System.out.println("Enter IV:");
String ivate = scc.nextLine();
byte[] iv = ivate.getBytes();
*/
System.out.println("IV=" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Cipher:");
String cipherText = sc.nextLine();
Scanner scanner = new Scanner(System.in); // object for scanner
System.out.println("Enter your Secret Key B:");
String encodedKeyB = scanner.nextLine();
byte[] decodedKeyB = Base64.getDecoder().decode(encodedKeyB);
SecretKey secretKeyB = new SecretKeySpec(decodedKeyB, 0, decodedKeyB.length, "AES");
// Initialize two key pairs
// KeyPair keyPairA = generateECKeys();
// KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
//SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
// keyPairB.getPublic());
//SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
// keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
// String cipherText = encryptString(secretKeyA, plainText);
// System.out.println("Encrypted cipher text: " + cipherText);
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println(" cipher text: " + cipherText);
System.out.println("Key: " + secretKeyB);
}
/* public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
| NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
*/
/* public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException
| NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
*/
/* public static String encryptString(SecretKey secretkeyB, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException
| NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException
| UnsupportedEncodingException | ShortBufferException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
*/
public static String decryptString(SecretKey secretkeyB, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(secretkeyB.getEncoded(),
secretkeyB.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength = cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
Artjom B 完全正确地指出,密钥生成需要为每一方单独进行。您需要做的是生成一个 class 来代表任何一方,或者仅包含共享方法,例如 generateKeyPair
、deriveSecretKey
,当然还有 receivePublicKey
。您应该能够将其用于 Sender
和 Receiver
classes.
仅仅输入密钥就完全破坏了最初执行密钥协商的想法。
但是,这不是您的代码的问题。
您在解密期间使用了静态随机 IV。 IV 在加密过程中应该是随机的,然后与解密密文的一方进行通信。这通常是通过在密文前加上 IV 前缀来实现的。
您需要在加密方法中生成 IV,而不是将其设为静态。以您的方式重用 IV 完全破坏了 GCM 模式的机密性,因为它在底层使用 CTR 模式。
请注意,GCM 模式 IV 应该是 12 个字节,而不是 16 个字节。GCM 模式 IV 可能只是 唯一(随机数,使用一次的数字)而不是随机的。
我有这段代码可以同时使用椭圆曲线密码术加密和解密文本消息。我把代码分成两部分:加密和解密。但是在解密过程中我得到了错误。谁能帮我解决一下。
共享代码:
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Scanner;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Enumeration;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class ENCRYPT {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
System.out.println("IV :" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Message:");
String plainText = sc.nextLine();
System.out.println("Original plaintext message: " + plainText);
// Initialize two key pairs
KeyPair keyPairA = generateECKeys();
KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
keyPairB.getPublic());
SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
String cipherText = encryptString(secretKeyA, plainText);
System.out.println("Encrypted cipher text: " + cipherText);
String encodedKeyA = Base64.getEncoder().encodeToString(secretKeyA.getEncoded());
String encodedKeyB = Base64.getEncoder().encodeToString(secretKeyB.getEncoded());
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println("Secret Key A: " + encodedKeyA);
System.out.println("Secret Key B: " + encodedKeyB);
}
public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException |
NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static String encryptString(SecretKey key, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
UnsupportedEncodingException | ShortBufferException |
IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
public static String decryptString(SecretKey key, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(key.getEncoded(),
key.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength += cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
解密密码:
//Decrypt
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class Decrypt {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
/* Scanner scc = new Scanner(System.in);
System.out.println("Enter IV:");
String ivate = scc.nextLine();
byte[] iv = ivate.getBytes();
*/
System.out.println("IV=" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Cipher:");
String cipherText = sc.nextLine();
Scanner scanner = new Scanner(System.in); // object for scanner
System.out.println("Enter your Secret Key B:");
String encodedKeyB = scanner.nextLine();
byte[] decodedKeyB = Base64.getDecoder().decode(encodedKeyB);
SecretKey secretKeyB = new SecretKeySpec(decodedKeyB, 0, decodedKeyB.length, "AES");
// Initialize two key pairs
// KeyPair keyPairA = generateECKeys();
// KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
//SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
// keyPairB.getPublic());
//SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
// keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
// String cipherText = encryptString(secretKeyA, plainText);
// System.out.println("Encrypted cipher text: " + cipherText);
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println(" cipher text: " + cipherText);
System.out.println("Key: " + secretKeyB);
}
/* public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
| NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
*/
/* public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException
| NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
*/
/* public static String encryptString(SecretKey secretkeyB, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException
| NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException
| UnsupportedEncodingException | ShortBufferException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
*/
public static String decryptString(SecretKey secretkeyB, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(secretkeyB.getEncoded(),
secretkeyB.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength = cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
Artjom B 完全正确地指出,密钥生成需要为每一方单独进行。您需要做的是生成一个 class 来代表任何一方,或者仅包含共享方法,例如 generateKeyPair
、deriveSecretKey
,当然还有 receivePublicKey
。您应该能够将其用于 Sender
和 Receiver
classes.
仅仅输入密钥就完全破坏了最初执行密钥协商的想法。
但是,这不是您的代码的问题。
您在解密期间使用了静态随机 IV。 IV 在加密过程中应该是随机的,然后与解密密文的一方进行通信。这通常是通过在密文前加上 IV 前缀来实现的。
您需要在加密方法中生成 IV,而不是将其设为静态。以您的方式重用 IV 完全破坏了 GCM 模式的机密性,因为它在底层使用 CTR 模式。
请注意,GCM 模式 IV 应该是 12 个字节,而不是 16 个字节。GCM 模式 IV 可能只是 唯一(随机数,使用一次的数字)而不是随机的。