I am trying to write a ssl decryption program. I found some old code from 2010 and have tried to get it to run. After finally being able to compile it I now get this error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class sun.security.ssl.CipherSuite from class sun.security.ssl.decrypt at sun.security.ssl.decrypt.main(decrypt.java:36)
which is the line where I call CipherSuite.valueOf(0x00, 0x2f); (deleted some comment lines that's why it might be another line number here)
Now I have read that it would probably be a problem with the method valueOf() being private. Since I am a newbie to java I don't know how to handle that, because the code I would need to change is in a jar. (Using openjdk-1.7)
On the other hand, it says here
that the method is just static. Also checking with .isAvailable() like recommended in the link above (at the .valueOf method) does not help.
Any suggestions?
Here is the code I got so far:
package sun.security.ssl;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.SecretKey;
import javax.xml.bind.DatatypeConverter;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import sun.security.internal.spec.TlsKeyMaterialParameterSpec;
import sun.security.internal.spec.TlsKeyMaterialSpec;
import sun.security.ssl.CipherSuite.BulkCipher;
public class decrypt {
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
byte[] clrnd = DatatypeConverter.parseHexBinary("be9b706c800f93526913732a356c7e7fe9383ace52f5ed120d38a81db07e903d");
byte[] srvrnd = DatatypeConverter.parseHexBinary("56af786428bc3e0c69ef2fdd9f6e3456ceae660a323d6109e9554b4af7fe6652");
ProtocolVersion pv = ProtocolVersion.valueOf(0x03, 0x03);
CipherSuite cipher_suite = CipherSuite.valueOf(0x00, 0x2f);
String KeyAlgo = cipher_suite.cipher.algorithm;
String Master_Key = "c55ca8dd56fa59b80b8ff01d9a1d4f04251aec41ab6340e8db118b3d4d2ef895cc51592f9bcd5dbde5eda9d5ad386f34";
byte[] master_secret = DatatypeConverter.parseBase64Binary(Master_Key);
byte[] client_app_data = DatatypeConverter.parseHexBinary("715e388b6ed9339faa6fc640f329c358");
SecretKey masterkey = new SecretKeySpec(master_secret, 0, master_secret.length, KeyAlgo);
//Calculate connection keys
BulkCipher cipher = cipher_suite.cipher;
int expandedKeySize = cipher_suite.exportable ? cipher.expandedKeySize : 0;
KeyGenerator kg = JsseJce.getKeyGenerator("SunTlsKeyMaterial");
int pv_major = pv.major;
int pv_minor = pv.minor;
try {
kg.init(new TlsKeyMaterialParameterSpec(masterkey, pv_major, pv_minor, clrnd, srvrnd, cipher.algorithm, cipher.keySize, expandedKeySize, cipher.ivSize, cipher_suite.macAlg.size, cipher_suite.prfAlg.getPRFHashAlg(), cipher_suite. prfAlg.getPRFHashLength(), cipher_suite.prfAlg.getPRFBlockSize()));
} catch (InvalidAlgorithmParameterException ex) {
Logger.getLogger(decrypt.class.getName()).log(Level.SEVERE, null, ex);
}
TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
SecretKey clntWriteKey = keySpec.getClientCipherKey();
IvParameterSpec clntWriteIV = keySpec.getClientIv();
SecureRandom clientrandom = new SecureRandom(clrnd);
CipherBox svbox = cipher_suite.cipher.newCipher(pv, clntWriteKey, clntWriteIV, clientrandom, false);
try {
svbox.decrypt(client_app_data, 5, client_app_data.length-5, 0);
} catch (BadPaddingException ex) {
Logger.getLogger(decrypt.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(svbox);
}
}
Thanks!
I guess because it uses the default access modifier.
Java Access Modifiers
The class sun.security.ssl.CipherSuite uses the default access modifier. This means that you can only access this class from the same package, which is not the case in your project.
CipherSuite class definition
Related
I'm trying to dynamically generate a pair of SSH keys in java, mimicking the behaviour of ssh-keygen. I intend to use those keys to communicate with an SSH server.
I have tried patching up and testing several pieces of code without success. The most recent piece of code I'm testing is this:
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator;
import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil;
import org.bouncycastle.crypto.util.OpenSSHPublicKeyUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;
import org.junit.jupiter.api.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.security.SecureRandom;
import java.security.Security;
public class GenKeysTest {
#Test
void testCase1() throws IOException {
Security.addProvider(new BouncyCastleProvider());
AsymmetricCipherKeyPairGenerator gen = new Ed25519KeyPairGenerator();
gen.init(new KeyGenerationParameters(new SecureRandom(), 255));
AsymmetricCipherKeyPair keyPair = gen.generateKeyPair();
byte[] priBytes = OpenSSHPrivateKeyUtil.encodePrivateKey(keyPair.getPrivate());
write(priBytes, "ed25519", "OPENSSH PRIVATE KEY");
byte[] pubBytes = OpenSSHPublicKeyUtil.encodePublicKey(keyPair.getPublic());
write(pubBytes, "ed25519.pub", "OPENSSH PUBLIC KEY");
}
public void write(byte[] bytes, String fileName, String type) throws IOException {
try (FileOutputStream out = new FileOutputStream(fileName)) {
try (PemWriter w = new PemWriter(new OutputStreamWriter(out))) {
w.writeObject(new PemObject(type, bytes));
}
}
}
}
I'm using the following dependencies:
dependencies {
implementation 'org.bouncycastle:bcprov-jdk15on:1.67'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.67'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
And I'm using these command to test the resulting keys:
ssh-keygen -l -f ed25519
ssh-keygen -l -f ed25519.pub
As far as I read, those commands should output the same text line which should look like this:
256 SHA256:REDACTED user#domain.com (ED25519)
Instead the output I get from ssh-keygen is similar to this:
ed25519.pub is not a public key file.
It would be very nice if someone could point me what am I missing.
As can be seen from the screenshot(https://jwt.io/) which is the expected signature, I am getting wrong java code. I am missing something very obvious wrong with code?
package com.company;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class Main {
public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException {
final Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec("qwertyuiopasdfghjklzxcvbnm123456".getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String sourcString = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2MjM5NTk5NDEsImV4cCI6MTY1NTQ5NTk0MSwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20ifQ";
byte[] signatureBytes = mac.doFinal(sourcString.getBytes(StandardCharsets.UTF_8));
System.out.println("Signatured=" + Base64.getEncoder().withoutPadding().encodeToString(signatureBytes));
}
}
OUTPUT : Signatured=ZFrcK6AZzYCTs0ugepzcSFMxxuY5Fs0PtMXGDZtT3sA
http://tpcg.io/P0MtSDC3
Looks like you almost got it, since you provide the SecretKeySpec in clear text you don't have to check this check box ... or provide a clear text SecretKey that actually encodes to "qwertyuiopasdfghjklzxcvbnm123456".
I have been trying to convert a Java class into DLL using IKVM.
IKVM converts that easily without errors. But while running it in VS, it throws the following exceptions:
System.TypeInitializationException: 'The type initializer for 'sun.security.jca.Providers' threw an exception.
**1 of 2 Inner Exceptions** : TypeInitializationException: The type initializer for 'java.security.Security' threw an exception.
**2 of 2 Inner Exceptions** : - InnerException {"Method not found: 'Void System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.Security.AccessControl.FileSystemRights, System.IO.FileShare, Int32, System.IO.FileOptions)'."} System.Exception {System.MissingMethodException}.
I can't understand the reason of these Exceptions.
My Java Code is :
package aesgzip;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.Scanner;
public class AESGzip {
private static final String key = MyKeyString;
private static final String IV = MyIV;
public static byte[] decrypt(byte[] encrypted) {
try {
IvParameterSpec IVSpec = new IvParameterSpec(IV.getBytes("UTF-8"));
SecretKeySpec KEYSpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(2, KEYSpec, IVSpec);
return cipher.doFinal(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
My C# Code is :
using System;
using aesgzip;
namespace AESTest
{
public partial class Form1 : Form
{
public Form1()
{
byte[] b = Convert.FromBase64String(myBASE64String);
byte[] x = AESGzip.decrypt(b);
Console.WriteLine(x);
}
}
}
I am trying to encrypt a string in ruby using Cipher with AES algorithm. I have example written in Java. I have taken help from this example and written code in Java but not able to get the same output as in JAVA.
Following is the code written in java
import java.util.Base64;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.util.Arrays;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HelloWorld {
public static final String PHONENUMBER_PARAM = "phoneNumber";
public static final String PIN_PARAM ="pin";
public static final String MERCHANTID_PARAM = "merchantId";
public static void main(String args[]) throws Exception {
String phoneNumber ="+917738995286";
String pin ="5577";
String merchantId ="527425858";
String encodedKey ="vPDkdTDrcygLPROzd1829A==";
String payLoad = PHONENUMBER_PARAM + "=" + URLEncoder.encode(phoneNumber, "UTF-8")+ "&" + PIN_PARAM + "=" + URLEncoder.encode(pin, "UTF-8") ;
byte[] decodedKey = Base64.getDecoder().decode(encodedKey.getBytes());
Key encryptionKey = new SecretKeySpec(decodedKey, "AES");
byte[] utf8Bytes = payLoad.getBytes("utf-8");
byte[] encryptedBody = encrypt(encryptionKey, utf8Bytes);
String encryptedData = new String(Base64.getEncoder().encode(encryptedBody));
System.out.println("encryptedData:" + encryptedData);
}
private static byte[] encrypt(Key encryptionKey, byte[] data) throws Exception {
Cipher c = Cipher.getInstance("AES");
c.init(1, encryptionKey);
return c.doFinal(data);
}
}
Output of this code is
encryptedData:lE40HlECbxU/mWRivF/+Szm3PprMoLW+Y7x911GczunakbG8l+A2JVEEP8gTw6xy
I tried to write the same code in ruby. Ruby Code is:
payLoad = "phoneNumber=%2B917738995286&pin=5577"
encodedKey = "vPDkdTDrcygLPROzd1829A=="
decodedKey = Base64.decode64(encodedKey)
dKey = decodedKey.each_byte.map { |b| b.to_s(16) }.join
cipher = OpenSSL::Cipher.new('aes128').encrypt
encryptionKey = cipher.update(dKey)
encryptionKey<< cipher.final
utf8Bytes = payLoad.bytes
uKey = utf8Bytes.map { |b| b.to_s(16) }.join
scipher = OpenSSL::Cipher.new('aes128').encrypt
scipher.key = encryptionKey
encryptedBody = scipher.update(uKey)
encryptedBody<< scipher.final
encryptedData = Base64.encode64(encryptedBody)
Output of this code is
CqFmCKJ004PsoXi2tDCTBmx7/iTHVyDsFH9y8NWNrEP3k3bOQp7h8uyl/a7Z\nYi9ZmcXSspo6FCyCo6fJIwPohg==\n
Don't know where is the error. I have already worked for 2 days but not able to get any answer. Any help will be great. Thanks in advance.
The following version outputs the same result as your Java code:
# crypt.rb
require 'base64'
require 'openssl'
payLoad = "phoneNumber=%2B917738995286&pin=5577"
encodedKey = "vPDkdTDrcygLPROzd1829A=="
decodedKey = Base64.decode64(encodedKey)
scipher = OpenSSL::Cipher.new('aes-128-ecb').encrypt
scipher.key = decodedKey
encryptedBody = scipher.update(payLoad)
encryptedBody << scipher.final
encryptedData = Base64.encode64(encryptedBody)
puts encryptedData
$ ruby crypt.rb
# => lE40HlECbxU/mWRivF/+Szm3PprMoLW+Y7x911GczunakbG8l+A2JVEEP8gT
# w6xy
Notable differences from your ruby script version:
You must specify the cipher mode. The problem is that Java defaults to the ECB mode whereas ruby defaults to the CBC mode. By the way, the ECB mode is considered less-secure today and you actually should not use it.
In ruby, you tried to re-encrypt the Base64-decoded version of your encryption key, which is something you don't do in the Java version.
In ruby, there is no need to do the string to byte conversions, you can encrypt strings right away.
So, although the two scripts output the same encrypted data now, I would strongly consider changing the AES mode of operation, to actually stay secure.
I am writing a JBenchX method that calculates a keys of CMSS signature using flexiprovider. I want to get timings for my method createKeys, but that is very very slow. Without annnotation #Bench that is too fast < 1 sec. Could you help to understand What's happen here?
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.keys.KeyPair;
import de.flexiprovider.api.keys.KeyPairGenerator;
import org.jbenchx.annotations.Bench;
import org.jbenchx.annotations.ForEachInt;
import org.jbenchx.annotations.ForEachString;
import org.jbenchx.annotations.SingleRun;
public class CMSSTest {
#Bench
public Object createKeys(#ForEachString({ "CMSSwithSHA1andWinternitzOTS_1" }) String cmss) throws NoSuchAlgorithmException {
Security.addProvider(new FlexiPQCProvider());
//byte[] signatureBytes = null;
KeyPairGenerator kpg = (CMSSKeyPairGenerator) Registry
.getKeyPairGenerator(cmss);
KeyPair keyPair = kpg.genKeyPair();
}
}
The actual output is and is active yet.
Initializing Benchmarking Framework...
Running on Linux Linux
Max heap = 1345847296 System Benchmark = 11,8ns
Performing 1 benchmarking tasks..
[0] CMSSTest.createObjectArray(CMSSwithSHA1andWinternitzOTS_1)!*!**!!!******!!******!****!****!!******!!!!*******!******!****!*********************************
The problem seems to be that Registry.getKeyPairGenerator creates a new KeyPairGenerator which is initialized using a 'true' random seed. For this, the system potentially has to wait for enough entropy to be available. Therefore, you should not do this as part of the code that you want to benchmark.
Try something like this:
import java.security.Security;
import org.jbenchx.annotations.Bench;
import org.jbenchx.annotations.ForEachString;
import de.flexiprovider.api.Registry;
import de.flexiprovider.api.exceptions.NoSuchAlgorithmException;
import de.flexiprovider.api.keys.KeyPair;
import de.flexiprovider.api.keys.KeyPairGenerator;
import de.flexiprovider.pqc.FlexiPQCProvider;
public class CMSSTest {
static {
Security.addProvider(new FlexiPQCProvider());
}
private final KeyPairGenerator kpg;
public CMSSTest(#ForEachString({"CMSSwithSHA1andWinternitzOTS_1"}) String cmss) throws NoSuchAlgorithmException {
this.kpg = Registry.getKeyPairGenerator(cmss);
}
#Bench
public Object createKeys() {
KeyPair keyPair = kpg.genKeyPair();
return keyPair;
}
}