-
-
Save zcdziura/7652286 to your computer and use it in GitHub Desktop.
import java.io.UnsupportedEncodingException; | |
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.jce.ECNamedCurveTable; | |
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; | |
public class Test { | |
public static byte[] iv = new SecureRandom().generateSeed(16); | |
public static void main(String[] args) { | |
String plainText = "Look mah, I'm a message!"; | |
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); | |
// Decrypt the message using 'secretKeyB' | |
String decryptedPlainText = decryptString(secretKeyB, cipherText); | |
System.out.println("Decrypted cipher text: " + decryptedPlainText); | |
} | |
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; | |
} | |
} |
Original plaintext message: Look mah, I'm a message! | |
Encrypted cipher text: 7AFCF3F9A6213FA6900D3DFC12553379580FC7AD362E2C2E28F548FC2AF42F07CF2B057537376F36 | |
Decrypted cipher text: Look mah, I'm a message! |
\Jarfiles>javac Test.java
Test.java:23: error: package org.bouncycastle does not exist
import org.bouncycastle.*;
^
Test.java:24: error: package org.bouncycastle.jce.spec does not exist
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
^
Test.java:54: error: cannot find symbol
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
^
symbol: class ECNamedCurveParameterSpec
location: class Test
Test.java:54: error: cannot find symbol
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
^
symbol: variable ECNamedCurveTable
location: class Test
4 errors
Iam getting these errors please help me out
Security Provider "BC" will not work from API level 28.
Try to add SpongyCastle manually:
Security.insertProviderAt(new BouncyCastleProvider(), 1);
add this to your build.gradle dependencies:
/* spongy castle */
implementation "com.madgag.spongycastle:core:1.58.0.0"
implementation "com.madgag.spongycastle:prov:1.58.0.0"
Make sure the BouncyCastleProvider() was coming from spongycastle:
import org.spongycastle.jce.provider.BouncyCastleProvider
Excuse me, I have occurred an error NoSuchAlgorithmException
:
java.lang.RuntimeException: Unable to start service com.example.helloworld.crypto.ecc.ECCService@1732d6 with Intent { cmp=com.example.helloworld/.crypto.ecc.ECCService (has extras) }: java.security.NoSuchAlgorithmException: no such algorithm: ECDH for provider BC
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3346)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1585)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6169)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
Caused by: java.security.NoSuchAlgorithmException: no such algorithm: ECDH for provider BC
at sun.security.jca.GetInstance.getService(GetInstance.java:87)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:206)
at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:286)
at com.example.helloworld.crypto.ecc.ECDH.generateKeyPair(ECDH.kt:11)
at com.example.helloworld.crypto.ecc.ECCService.testECDH(ECCService.kt:57)
at com.example.helloworld.crypto.ecc.ECCService.onStartCommand(ECCService.kt:16)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3329)
at android.app.ActivityThread.-wrap21(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1585)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6169)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)
It's my code:
class ECDH {
fun generateKeyPair(): KeyPair {
val parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1")
val keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "BC")
keyPairGenerator.initialize(parameterSpec)
return keyPairGenerator.generateKeyPair()
}
fun generateSharedSecret(privateKey: PrivateKey, publicKey: PublicKey): SecretKey? {
val keyAgreement = KeyAgreement.getInstance("ECDH", "BC")
keyAgreement.init(privateKey)
keyAgreement.doPhase(publicKey, true)
return keyAgreement.generateSecret("AES")
}
}
private fun testECDH() {
Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider())
var providers = Security.getProviders()
for (providers in providers) {
println("providers: $providers")
}
val ecdh = ECDH()
val keyPair = ecdh.generateKeyPair()
val keyPair1 = ecdh.generateKeyPair()
var secretKey = ecdh.generateSharedSecret(keyPair.private, keyPair1.public)
var secretKey1 = ecdh.generateSharedSecret(keyPair1.private, keyPair.public)
println("secretKey:$secretKey")
println("secretKey1:$secretKey1")
}
\Jarfiles>javac Test.java
Test.java:23: error: package org.bouncycastle does not exist
import org.bouncycastle.*;
^
Test.java:24: error: package org.bouncycastle.jce.spec does not exist
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
^
Test.java:54: error: cannot find symbol
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
^
symbol: class ECNamedCurveParameterSpec
location: class Test
Test.java:54: error: cannot find symbol
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
^
symbol: variable ECNamedCurveTable
location: class Test
4 errors
Iam getting these errors please help me out
You can download it at https://www.bouncycastle.org/latest_releases.html, and then put it in you project libs.
Excuse me, I have occurred an error
NoSuchAlgorithmException
:java.lang.RuntimeException: Unable to start service com.example.helloworld.crypto.ecc.ECCService@1732d6 with Intent { cmp=com.example.helloworld/.crypto.ecc.ECCService (has extras) }: java.security.NoSuchAlgorithmException: no such algorithm: ECDH for provider BC at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3346) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1585) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6169) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781) Caused by: java.security.NoSuchAlgorithmException: no such algorithm: ECDH for provider BC at sun.security.jca.GetInstance.getService(GetInstance.java:87) at sun.security.jca.GetInstance.getInstance(GetInstance.java:206) at java.security.KeyPairGenerator.getInstance(KeyPairGenerator.java:286) at com.example.helloworld.crypto.ecc.ECDH.generateKeyPair(ECDH.kt:11) at com.example.helloworld.crypto.ecc.ECCService.testECDH(ECCService.kt:57) at com.example.helloworld.crypto.ecc.ECCService.onStartCommand(ECCService.kt:16) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3329) at android.app.ActivityThread.-wrap21(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1585) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6169) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:781)It's my code:
class ECDH { fun generateKeyPair(): KeyPair { val parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1") val keyPairGenerator = KeyPairGenerator.getInstance("ECDH", "BC") keyPairGenerator.initialize(parameterSpec) return keyPairGenerator.generateKeyPair() } fun generateSharedSecret(privateKey: PrivateKey, publicKey: PublicKey): SecretKey? { val keyAgreement = KeyAgreement.getInstance("ECDH", "BC") keyAgreement.init(privateKey) keyAgreement.doPhase(publicKey, true) return keyAgreement.generateSecret("AES") } } private fun testECDH() { Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider()) var providers = Security.getProviders() for (providers in providers) { println("providers: $providers") } val ecdh = ECDH() val keyPair = ecdh.generateKeyPair() val keyPair1 = ecdh.generateKeyPair() var secretKey = ecdh.generateSharedSecret(keyPair.private, keyPair1.public) var secretKey1 = ecdh.generateSharedSecret(keyPair1.private, keyPair.public) println("secretKey:$secretKey") println("secretKey1:$secretKey1") }
I solved the problem,
change KeyPairGenerator.getInstance("ECDH", "BC")
to KeyPairGenerator.getInstance("ECDH", org.bouncycastle.jce.provider.BouncyCastleProvider())
@ zcdziura Hi, I just wanted to understand the example which you have shared uses an asymmetric form of encryption or symmetric. I am asking this question as to when I implemented this solution and after generating a shared secret I am getting both the key as same. So I am a bit doubtful about this. It will be great if you can help me to understand this.
The private and public keys are the same in the keypair.
Hi Team ,
I am try to convert KeyPair to String but unfortunately I am not able to convert String to KeyPair. Can you help me out in this.
Below is mention which I try.
KeyPair keyPairA = generateECKeys();
String p= keyPairA.toString();
//Need again to convert p to KeyPair