Spring Security: Simple Encryption / decryption not working: InvalidKeyException - java

I'm trying to write a very simple program to encrypt and decrypt a string:
String password = "kdfljxcasd";
String encodeThat = "Hello World + some special chars!^^-";
String salt = KeyGenerators.string().generateKey();
BytesEncryptor encryptor = Encryptors.standard(password, salt);
// breakpoint steping doesn't reach that point - it gets stuck here for some reason...
byte[] encrypted = encryptor.encrypt(encodeThat.getBytes());
byte[] decrypted = encryptor.decrypt(encrypted);
System.out.println("Before encryption: " + encodeThat);
System.out.println("Encrypted: " + encrypted.toString());
System.out.println("After encryption: " + decrypted.toString());
But for some reason I never get an encrypted value. When I call enryptor.encrypt() it never reaches that point.
I'm getting the following exception:
'Unable to initialize due to invalid secret key' java.lang.IllegalArgumentException: Unable to initialize due to invalid secret key
What am I doing wrong?

Ok, after hours of searching I finally found the solution:
Appearently I didn't have the correct policies for unlimited Strength installed.
That's the way I solved it:
Download the policies from: http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
Unpack that and put local_policy.jar and US_export_policy.jar into ${jdk -path}/jre/lib/security and override the existing files. (ATTENTION: Don't put it in the JRE folder. You have to put it into jdk/jre/... ... - that took me hours :) )
Restart the server and it works!
Hope that helped :)

Since Java 8u151 you can resolve this with a property:
Security.setProperty("crypto.policy", "unlimited");

Try to upgrade to newer java 8 JDK version.
For me I tried 2 versions:
1.8.131 - failed
1.8.201 - success

Ran into this problem and fixed it by switching from JDK 1.8 to Adopt Open JDK 8

Related

Bouncy Castle is throwing "mac check in OCB failed" when trying to decrypt an AES message

I need to decrypt an AES message. I was able to make it work on python(using the pycryptodome library) but I wasn't successful on kotlin/java. Since the decryption mode is OCB and Java does not support it by default, I had to use the Bouncy Castle library.
Here's the working python code:
def decrypt_aes_message(shared_key, encrypted_message):
encrypted_msg = b64decode(encrypted_message["encryptedMessage"].encode())
tag = b64decode(encrypted_message["tag"].encode())
nonce = b64decode(encrypted_message["nonce"].encode())
cipher = AES.new(shared_key.encode(), AES.MODE_OCB, nonce=nonce)
return cipher.decrypt_and_verify(encrypted_msg, tag).decode()
Here's the java code:
fun decryptAesMessage2(sharedKey: String, encryptedMessageData: Map<String, String>): ByteArray {
var encryptedMessage = encryptedMessageData["encryptedMessage"]!!.utf8Base64Decode()
var tag = encryptedMessageData["tag"]!!.utf8Base64Decode()
var nonce = encryptedMessageData["nonce"]!!.utf8Base64Decode()
var key = KeyParameter(sharedKey.toByteArray(Charsets.UTF_8))
var params = AEADParameters(key, tag.size*8, nonce)
var cipher = OCBBlockCipher(AESEngine(), AESEngine())
cipher.init(false, params)
val out = ByteArray(cipher.getOutputSize(encryptedMessage.size))
var offset = cipher.processBytes(encryptedMessage, 0, encryptedMessage.size, out, 0)
offset += cipher.doFinal(out, offset) // Throwing exception here
return out
}
The java code is throwing the exception org.bouncycastle.crypto.InvalidCipherTextException: mac check in OCB failed on cipher.doFinal
The file debug.zip has the complete problem reproducer.
Inside the zip file you'll find:
py_working_code.py - the working python script(needs pycryptodome in order to work. You can install pycryptodome using pip install pycryptodome)
bc-debug - gradle project reproducing the problem
There are two issues, one is a bug in your Kotlin code, the other is a library bug:
Bug in Kotlin code
While PyCryptodome processes ciphertext and tag separately, BC/Kotlin expects the concatenation of both in the order: ciphertext|tag.
Therefore the line encryptedMessage += tag must be added in the Kotlin code:
fun decryptAesMessage2(sharedKey: String, encryptedMessageData: Map<String, String>): ByteArray {
var encryptedMessage = encryptedMessageData["encryptedMessage"]!!.utf8Base64Decode()
var tag = encryptedMessageData["tag"]!!.utf8Base64Decode()
encryptedMessage += tag // Fix
var nonce = encryptedMessageData["nonce"]!!.utf8Base64Decode()
var key = KeyParameter(sharedKey.toByteArray(Charsets.UTF_8))
var params = AEADParameters(key, tag.size*8, nonce)
var cipher = OCBBlockCipher(AESEngine(), AESEngine())
cipher.init(false, params)
val out = ByteArray(cipher.getOutputSize(encryptedMessage.size))
var offset = cipher.processBytes(encryptedMessage, 0, encryptedMessage.size, out, 0)
offset += cipher.doFinal(out, offset) // Throwing exception here
return out
}
Test: Below, identical test data is successfully decrypted using the Python code and the fixed Kotlin code:
Python:
encrypted_message = {
'encryptedMessage': 'LzoelJ9Nv4cruj0JUlxFrNR+mqyO2rvwqDHYwnj0OkvJ+BBvug+ORYVkxA==',
'tag': 'hl56drXePWiLkVavVwF3/w==',
'nonce': b64encode(b'012345678901').decode()
}
dt = decrypt_aes_message('01234567890123456789012345678901', encrypted_message)
print(dt) # The quick brown fox jumps over the lazy dog
Kotlin:
val encrypted_message = mutableMapOf<String, String>()
encrypted_message["encryptedMessage"] = "LzoelJ9Nv4cruj0JUlxFrNR+mqyO2rvwqDHYwnj0OkvJ+BBvug+ORYVkxA=="
encrypted_message["tag"] = "hl56drXePWiLkVavVwF3/w=="
encrypted_message["nonce"] = Base64.getEncoder().encodeToString("012345678901".toByteArray(Charsets.UTF_8))
val dt = decryptAesMessage2("01234567890123456789012345678901", encrypted_message)
println(String(dt, Charsets.UTF_8)) // The quick brown fox jumps over the lazy dog
Library bug
Another problem is that both implementations produce different results for a nonce length of 120 bits (15 bytes), the maximum allowed nonce length for OCB (see RFC 7253, 4.2. Encryption: OCB-ENCRYPT):
The following test uses a fixed key and plaintext and compares the results between the Python and BC/Kotlin code for nonce lengths 13, 14, and 15 bytes:
Key: b'01234567890123456789012345678901'
Plaintext: b'testmessage'
Nonce Länge 13 bytes 14 bytes 15 bytes
Nonce b'0123456789012' b'01234567890123' b'012345678901234'
Python (ct|tag) 0xb35a69a245ab18fe3b6bae38b179c2a43b341f67c0451256b76bd7 0xff9be97fcb6e1ac57e6997bc3e84598a83ab70947ccac500fcf75e 0xff9be97fcb6e1ac57e6997bc3e84598a83ab70947ccac500fcf75e
BC/Kotlin 0xb35a69a245ab18fe3b6bae38b179c2a43b341f67c0451256b76bd7 0xff9be97fcb6e1ac57e6997bc3e84598a83ab70947ccac500fcf75e 0xa4355068324065f2ad194b058bdb86caa67c225b99021dbd588034
The Python implementation returns the same ciphertext/tag for nonce lengths 14 and 15, while the results for BC/Kotlin differ. This indicates a bug in the Python implementation.
Unfortunately, RFC 7253, Appendix A. Sample Results only provides test vectors whose nonces are all 12 bytes in size, so the bug cannot be assigned more clearly.
I.e. if you use a 15 bytes nonce, both implementations are not compatible, where the problem is most likely caused by the Python implementation.
Edit
Analysis of linked example:
You are affected by both bugs. According to your comment, you have already fixed the bug in the Kotlin code (concatenation of ciphertext and tag). Since the nonce you used in the example is 15 bytes (knQgYf1MsOs8smx9GtWM corresponds Base64 decoded to 0x92742061fd4cb0eb3cb26c7d1ad58c) the bug described in the second part of my answer is the cause of the problem. This bug is not in your code, but in one of the libraries, most likely in the Python library. Therefore you cannot fix it (at least not without greater effort).
Workarounds
As shown in the above test, the Python code for a nonce length of 15 bytes seems to simply ignore the 15th byte, i.e. if you use the 14 bytes nonce knQgYf1MsOs8smx9GtU= (0x92742061fd4cb0eb3cb26c7d1ad5) in your Python code, the Python code returns the same ciphertext and the same tag as with the 15 bytes nonce knQgYf1MsOs8smx9GtWM, which is why decryption with the 14 bytes nonce is also possible:
key = "f009Cip5hM4Obbb6E2MT5npJBHlc82vD"
message_data = {"encryptedMessage":"XMQx/xbVVTbMdpMiTXVp5XPICm11Vw2pgALpVI0NgbdqLLmikhPuu9M+qQzyOVZlZZBRlscijpyAZDsLGcTSPP54O35oKNp//PuOrWsN/ZZMkCByKCSBysJLRiZV1OjZDg01gi5/nYNbUgGGd8uRGKfBaKjjXngZ1J89GOvDeWPQcjbfbdzd9w+jbZGZ5jnAIChOL1Uqohf+6KHtjR/H06fFTHwB1abzAQrGbCNBNXBmN9+zEu7Auy3NPWKrZ+SL5Nk=","tag":"ZcqXSBqYU5TjgdMC+bMeUQ==","nonce":"knQgYf1MsOs8smx9GtU="}
decrypted_message = decrypt_aes_message (key, message_data)
print (decrypted_message) # https://app.passiv.com/snapTrade/redeemToken?token=v9uJsXYsi%2B6s9kyohisc6DFntJ/yD6m/2zhmO5xp6Vmezcyi8nwx63YtkqnnaogZvFmqs7L99EtZ0mxN9mAQTNoThHj3GaypXXUdiQIzig%3D%3D&clientId=SCANZ&broker=ALPACA
If you use this 14 bytes nonce knQgYf1MsOs8smx9GtU= in the Kotlin code, the decryption is also successful. This is the workaround for this specific example!
The general workaround, as long as the library bug is not fixed, is not to use a 15 bytes nonce, but only a maximum 14 bytes nonce!
On this website there are also testvectors with 15 bytes nonces listed. As expected, these are not met by the PyCryptodome implementation. I have filed an issue on PyCryptodome based on one of the 15 bytes nonce test vectors: Issue #664.

Reading encrypted private key in PKCS#8 format through bouncycastle, Java failing in docker container

I am trying to read a PKCS#8 private key which looks like following:
key.k8 --> (Sample key. Passphrase - 123456):
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILbKY9hPxYSoCAggA
MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBCvaGt2Hmm2NpHpxbLvHKyOBIIE
0IQ7dVrAGXLZl0exYIvyxLAu6zO00jL6b3sb/agTcCFOz8JU6fBanxY0d5aYO4Dn
mynQG7BoljU470s0zIwW/wk0MmdUFl4nXWBX/4qnG0sZqZ9KZ7I8R/WrBkmpX8C/
4pjdVhu8Ht8dfOYbkbjMBTohDJz8vJ0QwDIXi9yFjjef+QjwrFOl6kAeDJFVMGqc
s7K/wOnhsL1XxfW9uTulPiZh5YTZKcatMkeGDR7c+cg5I+Mutim92diWuCekhNoa
uvhUy1M3cbs7Azp1Mhz+V0CDKklI95EvN4u23WhiJPCjAofC/e45/heOP3Dwm7WZ
zHEY1C/X8PsTl6MEEIF3ZJP+4Vr0corAs1L2FqE6oOng8dFFYmF5eRyBx6bxFd05
iYbfOH24/b3qtFKPC689kGEd0gWp1dwES35SNNK+cJqVRTjgI0oKhOai3rhbGnmp
tx4+JqploQgTorj4w9asbtZ/qZA2mYSSR/Q64SHv7LfoUCI9bgx73MqRQBgvI5yS
b4BoFBnuEgOduZLaGKGjKVW3m5/q8oiDAaspcSLCJMIrdOTYWJB+7mfxX4Xy0vEe
5m2jXpSLQmrfjgpSTpHDKi/3b6OzKOcHjSFBf8IoiHuLc5DVvLECzDUxxaMrTZ71
0YXvEPwl2R9BzEANwwR9ghJvFg1Be/d5W/WA1Efe6cNQNBlmErxD6l+4KDUgGjTr
Aaksp9SZAv8uQAsg7C57NFHpTA5Hznr5JctL+WlO+Gk0cAV6i4Py3kA6EcfatsnS
PqP2KbxT+rb2ATMUZqgWc20QvDt6j0CTA1BuVD1PNhnAUFvb2ocyEEXOra22DPPS
UPu6jirSIyFcjqFjJ9A1FD9L4/UuX2UkDSLqblFlYB1+G55KZp+EKz8SZoN5qXy1
LyMtnacEP5OtRDrOjopzVNiuV1Uv63M9QVi1hZlVLJEomgjWuvuyEuIwDaY2uryW
vx+jJEZyySFkb1JwAbrm+p6sCTFnbQ/URKC2cit/FJyKqNim6VQvGL8Sez34qV3z
D13QJgTZfsy+BaZoaQ6cJTXtJ8cN0IcQciOiDNBKMW66zO6ujS8G+KNviNQypDm6
h4sOgjMqLaZ4ezPEdNj/gaxV7Y15nVRu0re8dVkaa5t9ft/sh6A+yeTD5tS5hHkf
NI7uJPTaTXVoz7xq2PAJUTWujMLMZKtmNOzNqYvxWRy3tCOFobBQkMxqEBEwHd+x
SA+gFcJKJ+aNfCGZJ5fFr8rNlhtOF6uMwOAlfiUlP/pCUDUCKPjZVj4K95yNc8Io
jSZSPb5tGPe0HqXgc6IAfQarlUZt90oVtzL0OfOfTxe1bEzS2ccNadbx/6vjLBc4
q5UuUBppl3rXpbuZ7J1Rp3n2byF4APxFdT2LHKq+MYMfWUToau/TCMT4lFIM9tM8
7TuuyUT2PKzf/xlsl4iScw96z9xxGPQrXn7IA2W5iL+0eCLztJdjNRX1FisdfIBL
PraOVlmF8jHKbFdRZ8Yi8pApbQjvHi24g7dX7u/cq1FH/VE+nJ0O8YVCYVDw13CW
h0p7yD7BuB0R+0WnR0yvkp30vK4/rtCB+Ob8bH/+HvAZrAU5X8jq/wsQbLkrLHZV
6A6GGfX8+hy5AoaXsH1BHnMyXkaF6Mv29z8JcslDJxX/
-----END ENCRYPTED PRIVATE KEY-----
Following code is being used to parse the private key:
InputStream privateKeyInputStream = getPrivateKeyInputStream(); // reads the key file from classpath and share as DataStream
logger.info("InputStreamExists --> {} ", privateKeyInputStream.available());
PEMParser pemParser = new PEMParser(new InputStreamReader(privateKeyInputStream));
Object pemObject = pemParser.readObject();
if (pemObject instanceof PKCS8EncryptedPrivateKeyInfo) {
// Handle the case where the private key is encrypted.
PKCS8EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = (PKCS8EncryptedPrivateKeyInfo) pemObject;
InputDecryptorProvider pkcs8Prov =
new JceOpenSSLPKCS8DecryptorProviderBuilder().build(passphrase.toCharArray());
privateKeyInfo = encryptedPrivateKeyInfo.decryptPrivateKeyInfo(pkcs8Prov); // fails here
}
InputStream resourceAsStream = null;
if ("local".equals(privateKeyMode)) {
resourceAsStream = this.getClass().getResourceAsStream(privateKeyPath);
} else {
File keyFile = new File(privateKeyPath);
logger.info(
"Key file found in {} mode. FileName : {}, Exists : {}",
privateKeyMode,
keyFile.getName(),
keyFile.exists());
try {
resourceAsStream = new DataInputStream(new FileInputStream(keyFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
When I am running this code through intelliJ on windows, the code works fine but when I run it through docker container I am getting following exception:
org.bouncycastle.pkcs.PKCSException: unable to read encrypted data: failed to construct sequence from byte[]: Extra data detected in stream
snowflake-report-sync | at org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo.decryptPrivateKeyInfo(Unknown Source) ~[bcpkix-jdk15on-1.64.jar!/:1.64.00.0]
snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getPrivateKey(SnowFlakeConfig.java:103) ~[classes!/:na]
snowflake-report-sync | at com.optum.snowflakereportsync.configuration.SnowFlakeConfig.getConnectionProperties(SnowFlakeConfig.java:67) ~[classes!/:na]
Following is Dockerfile used:
FROM adoptopenjdk/openjdk11-openj9:latest
COPY build/libs/snowflake-report-sync-*.jar snowflake-report-sync.jar
RUN mkdir /encryption-keys
COPY encryption-keys/ /encryption-keys/ #keys are picked from docker filesystem when running in container
EXPOSE 8080
CMD java -Dcom.sun.management.jmxremote -noverify ${JAVA_OPTS} -jar snowflake-report-sync.jar
Options tried:
Ensured that key file is being read while running in container. Logger "InputStreamExists --> {}" gives number of bytes
Ran dos2unix on key.k8 just to make sure there are no Window's "^M" characters which be could be causing issue as container is linux one : FROM adoptopenjdk/openjdk11-openj9:latest
Not sure what I am doing wrong but any help or pointers would be appreciated.
Like #Bragolgirith suspected, BouncyCastle seems to have problems with OpenJ9. I guess it is not a Docker issue, because I can reproduce it on GitHub Actions, too. It is also not limited to BouncyCastle 1.64 or 1.70, it happens in both versions. It also happens on OpenJ9 JDK 11, 14, 17 on Windows, MacOS and Linux, but for the same matrix of Java and OS versions it works on Adopt-Hotspot and Zulu.
Here is an example Maven project and a failed matrix build. So if you select another JVM type, you should be fine. I know that #Bragolgirith already suggested that, but I wanted to make the problem reproducible for everyone and also provide an MCVE, in case someone wants to open a BC or OpenJ9 issue.
P.S.: It is also not a character set issue with the InputStreamReader. This build fails exactly the same as before after I changed the constructor call.
Update: I have created BC-Java issue #1099. Let's see what the maintainers can say about this.
Update 2: The solution to your problem is to explicitly set the security provider to BC for your input decryptor provider. Thanks to David Hook for his helpful comment in #1099.
BouncyCastleProvider securityProvider = new BouncyCastleProvider();
Security.addProvider(securityProvider);
// (...)
InputDecryptorProvider pkcs8Prov = new JceOpenSSLPKCS8DecryptorProviderBuilder()
// Explicitly setting security provider helps to avoid ambiguities
// which otherwise can cause problems, e.g. on OpenJ9 JVMs
.setProvider(securityProvider)
.build(passphrase.toCharArray());
See this commit and the corresponding build, now passing on all platforms, Java versions and JVM types (including OpenJ9).
Because #Bragolgirith mentioned it in his answer: If you want to avoid the explicit new JceOpenSSLPKCS8DecryptorProviderBuilder().setProvider(securityProvider), the call Security.insertProviderAt(securityProvider, 1) instead of simply Security.addProvider(securityProvider) would in this case also solve the problem. But this holds true only as long as no other part of your code or any third-party library sets another provider to position 1 afterwards, as explained in the Javadoc. So maybe it is not a good idea to rely on that.
Edit:
On second thought, when creating the JceOpenSSLPKCS8DecryptorProviderBuilder, you're not explicitly specifying the provider:
new JceOpenSSLPKCS8DecryptorProviderBuilder()
.setProvider(BouncyCastleProvider.PROVIDER_NAME) // add this line
.build(passphrase.toCharArray());
It seems OpenJ9 uses a different provider/algo selection mechanism and selects the SunJCE's AESCipher class as CipherSpi by default, while Hotspot selects BouncyCastleProvider's AES class.
Explicitly specifying the provider should work in all cases.
Alternatively, when adding the BouncyCastleProvider you could insert it at the first preferred position (i.e. Security.insertProviderAt(new BouncyCastleProvider(), 1) instead of Security.addProvider(new BouncyCastleProvider())) so that it gets selected.
(It's still unclear to me why the provider selection mechanism differs between the different JVMs.)
Original post:
I've managed to reproduce the issue and at this point I'd say it's an incompatibility issue with the OpenJ9 JVM.
Starting from a Hotspot base image instead, e.g.
FROM adoptopenjdk:11-jre-hotspot
makes the code work.
(Not yet entirely sure whether the fault lies with the Docker image itself, the OpenJ9 JVM or BouncyCastle)

SecretKeyFactory Not Available (Jasypt)

I am trying to encrypt a string using Jasypt 1.9.3 and my JDK version is 1.8.0_281.
This is the code I am have written:
Security.setProperty("crypto.policy", "unlimited");
if (pooledPBEStringEncryptor == null) {
pooledPBEStringEncryptor = new PooledPBEStringEncryptor();
pooledPBEStringEncryptor.setPassword(encryptionKey);
pooledPBEStringEncryptor.setAlgorithm("PBEWITHHMACSHA512ANDAES256");
pooledPBEStringEncryptor.setPoolSize(4);
pooledPBEStringEncryptor.setSaltGenerator(new RandomSaltGenerator());
}
encrypted = pooledPBEStringEncryptor.encrypt(cValue);
But when I run it, I get the error
Exception in thread "main" java.lang.RuntimeException: Security Error in doEncrypt: org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: PBEWITHHMACSHA512ANDAES256 SecretKeyFactory not available
I ran the AlgorithmRegistry.getAllPBEAlgorithms() and my output is:
PBEWITHHMACSHA1ANDAES_128, PBEWITHHMACSHA1ANDAES_256, PBEWITHHMACSHA224ANDAES_128, PBEWITHHMACSHA224ANDAES_256, PBEWITHHMACSHA256ANDAES_128, PBEWITHHMACSHA256ANDAES_256, PBEWITHHMACSHA384ANDAES_128, PBEWITHHMACSHA384ANDAES_256, PBEWITHHMACSHA512ANDAES_128, PBEWITHHMACSHA512ANDAES_256, PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_128, PBEWITHSHA1ANDRC2_40, PBEWITHSHA1ANDRC4_128, PBEWITHSHA1ANDRC4_40
When I use the algorithm PBEWITHHMACSHA256ANDAES_256 I get a different error.
Exception in thread "main" java.lang.RuntimeException: Security Error in doEncrypt: org.jasypt.exceptions.EncryptionOperationNotPossibleException
I am a little lost as to what to do.
I have downloaded the unlimited policy jars from Oracle and saved them in JAVA_HOME\jre\lib\security\ folder. And I am on Windows.
The code lacks the specification of the IV generator with setIvGenerator(), e.g.:
pooledPBEStringEncryptor.setIvGenerator(new RandomIvGenerator());
By default, NoIvGenerator is used, which causes the exception because the algorithm applies the CBC mode, which requires an IV.
The default salt generator, by the way, is RandomSaltGenerator, so this would not necessarily need to be specified with setSaltGenerator().
The PooledPBEStringEncryptor#encrypt() method returns the Base64 encoded concatenation of salt (16 bytes), IV (16 bytes) and ciphertext.
The exception org.jasypt.exceptions.EncryptionOperationNotPossibleException is a general exception that is generated in many error situations and is therefore not very meaningful, see here. This includes e.g. the missing of the JCE Unlimited Strength Jurisdiction Policy (which however seems to be installed on your system).
For completeness: The algorithm is called PBEWITHHMACSHA512ANDAES_256 (which you have already figured out yourself).
PBEWITHHMACSHA512ANDAES_256 derives a 32 bytes key for AES-256 from password and salt using PBKDF2. HMAC/SHA512 is applied. Since not explicitly specified, the default iteration count of 1000 is used. The algorithm applies the CBC mode for encryption (which is why the IV is needed).

Java Bouncycastle Generate Ed25519 OpenSSH Private Key File Failing

I've been trying to programatically generate OpenSSH host keys in my Java application, but I'm unable to get a working Ed25519 key in the OpenSSH v1 key format. My current thought is that there's a problem with OpenSSHPrivateKeyUtil, but I'm not sure how to verify that. Here's my current attempt:
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.util.OpenSSHPrivateKeyUtil;
import java.util.Base64;
...
Ed25519PrivateKeyParamters keyParamters = new Ed25519PrivateKeyParamters(new SecureRandom());
byte[] encodedPrivateKey = OpenSSHPrivateKeyUtil.encodePrivateKey(keyParameters);
System.out.println(Base64.getEncoder().encodeToString(encodedPrivateKey));
The output looks like what I'm expecting (similar to the results of an ssh-keygen -t ed25519), but when I put the results into /etc/ssh/sshd_host_ed25519_key (and the corresponding public key into /etc/ssh/sshd_host_ed25519_key.pub), I get the following error from sshd in /var/log/messages:
auth.err: error: Could not load host key: /etc/ssh/sshd_host_ed25519_key
I'm using the following:
centos 7.6
java 1.8.0_212
openssh 7.4p1-16.e17
bouncycastle 1.63
Any help would be appreciated, thanks.

Cryptography - RSA Algorithm in Java 1.4

I am using Java 1.4.2_10 and I am trying to use RSA encryption:
I am getting the NoSuchAlgorithmException for the following code:
cipher = Cipher.getInstance("RSA");
This is the error:
java.security.NoSuchAlgorithmException: Cannot find any provider supporting RSA
at javax.crypto.Cipher.getInstance(DashoA6275)
This works fine in 1.5 and above, however I need to use 1.4. Is there any workaround or thirdparty product that I can use to fix this?
Thanks in advance.
You can install the Bouncy Castle cryptography provider. Just grab their jars and then call Cipher.getInstance("RSA", "BC")
Java 1.4 definitely supports RSA, so the fact that this isn't working suggests that something deeper is wrong. Does this work with any other ciphers (such as "AES" or "DES")? You should check to make sure your providers are properly configured. What is the output of the following code on your system:
System.out.println("Providers: ");
java.security.Provider[] providers = java.security.Security.getProviders();
for(int x = 0; x < providers.length; x++) {
System.out.println("\t" + providers[x]);
}
System.out.println();
System.out.println("Algorithms: ");
java.util.Set algs = java.security.Security.getAlgorithms("Cipher");
java.util.Iterator i_algs = algs.iterator();
while(i_algs.hasNext()) {
System.out.println("\t" + i_algs.next());
}

Categories

Resources