Jasypt with the Bouncy Castle JCE SHA512 encryption - encryption

I need:
password based encryption using sha512 digesting and 256 bit AES encryption with cbc and bc flags set.
Seems that algorithm should be like this: PBEWithSHA512AndAES256-CBC-BC
but in my local env I get error: org.jasypt.exceptions.EncryptionInitializationException: java.security.NoSuchAlgorithmException: no such algorithm: PBEWithSHA512AndAES256-CBC-BC for provider BC
my test code:
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
public class App {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void main(String[] args) {
StandardPBEStringEncryptor mySecondEncryptor = new StandardPBEStringEncryptor();
mySecondEncryptor.setProviderName("BC");
// mySecondEncryptor.setAlgorithm("PBEWITHSHA256AND128BITAES-CBC-BC");
mySecondEncryptor.setAlgorithm("PBEWithSHA512AndAES256-CBC-BC");
mySecondEncryptor.setPassword("pass");
String myText = "Mindaugas";
String mySecondEncryptedText = mySecondEncryptor.encrypt(myText);
System.out.println(mySecondEncryptedText);
System.out.println(mySecondEncryptor.decrypt(mySecondEncryptedText));
}
}
PBEWITHSHA256AND128BITAES-CBC-BC - this algorithm works fine but I need sha512 and 256 bit AES...
I have installed extensions form: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
but still get this error: no such algorithm

Since the list of algorithms on the bouncycastle website is not updated, looking at the code in the constructor in the Java file BouncyCastleProvider.java, you can find an exhaustive list of algorithms which are supported by bcprov-jdk16. A small list (of the type of algorithms/functions you were looking for) supported is -
PBEWITHSHAAND128BITAES-CBC-BC
PBEWITHSHAAND192BITAES-CBC-BC
PBEWITHSHAAND256BITAES-CBC-BC
PBEWITHSHA256AND128BITAES-CBC-BC
PBEWITHSHA256AND192BITAES-CBC-BC
PBEWITHSHA256AND256BITAES-CBC-BC
PBEWITHSHA1AND128BITAES-CBC-BC
PBEWITHSHA1AND192BITAES-CBC-BC
PBEWITHSHA1AND256BITAES-CBC-BC
PBEWITHSHA-1AND128BITAES-CBC-BC
PBEWITHSHA-1AND192BITAES-CBC-BC
PBEWITHSHA-1AND256BITAES-CBC-BC
PBEWITHSHA-256AND128BITAES-CBC-BC
PBEWITHSHA-256AND192BITAES-CBC-BC
PBEWITHSHA-256AND256BITAES-CBC-BC

Related

How to decode the OpenLR string in a HERE Traffic API v7 response?

I'm currently building a client that requests Traffic Flow data from the Traffic API v7:
https://data.traffic.hereapi.com/v7/flow?locationReferencing=olr&…
I would like to decode the OpenLR Location Referencing string contained in the response, but I'm not using Java nor Scala so I cannot use the libraries provided.
Returned strings look like this:
"olr": "CCoBEAAmJQm+WSVVfAAJBQQCAxoACgUEAogZAAHtA2UACQUEAgOEADBigj0="
I've read the paragraph on the difference between TISA OLR and TomTom OpenLR, and I am able to find online decoders for the TomTom OpenLR strings as well as some libraries in various languages; but none of those work for the OpenLR string that the HERE API returns.
Are there any resources (source code, online decoders, further documentation) that have details on decoding OpenLR strings used by HERE?
HERE Location Lib would do it for you.
import com.here.platform.location.referencing.olr.OlrPrettyPrinter;
import com.here.platform.location.tpeg2.BinaryMarshallers;
import com.here.platform.location.tpeg2.olr.LinearLocationReference;
import com.here.platform.location.tpeg2.olr.OpenLRLocationReference;
import java.io.ByteArrayInputStream;
import java.util.Base64;
public class decode {
public static void main(final String[] args) {
byte[] decode = Base64.getDecoder().decode("CCoBEAAmJQm+WSVVfAAJBQQCAxoACgUEAogZAAHtA2UACQUEAgOEADBigj0=");
OpenLRLocationReference reference =
BinaryMarshallers.openLRLocationReference()
.unmarshall(new ByteArrayInputStream(decode));
System.out.println(OlrPrettyPrinter.prettyPrint((LinearLocationReference) reference.getLocationReference()));
}
}
output below:
type: OLR LinearLocationReference
positiveOffset: DistanceMetresMax15000(98)
negativeOffset: DistanceMetresMax15000(317)
firstReferencePoint:
coordinate: 2446716,638553 => 52.50083,13.701861
lineProperties:
bearing: 26 => 36.6°
frc: 2 (0-7, with 0 most important)
fow: 3 => single carriageway
pathProperties:
lfrcnp: 2 (0-7, with 0 most important)
dnp: 1049 m
againstDrivingDirection: false
intermediateReferencePoints: ∅
lastReferencePoint:
coordinate: 869,493 => 52.50952,13.706791
lineProperties:
bearing: 132 => 185.6°
frc: 2 [0-7], with 0 most important
fow: 3 => single carriageway

Convert ssh public keys from various formats to Open SSH with node-forge

I'd like to convert ssh public keys provided in various formats into the Open SSH format using node-forge.
I have no problem generating the keys and converting with:
forge.ssh.publicKeyToOpenSSH(key, comment);
but cannot figure out how to read the files into node-forge, Tried:
pki.publicKeyFromPem(pem);
or
pki.publicKeyFromAsn1(subjectPublicKeyInfo);
You can load OpenSSL public keys (PKCS#8) like this:
var forgePubKey = forge.pki.publicKeyFromPem('-----BEGIN PUBLIC KEY-----' + publicKey + '-----END PUBLIC KEY-----');
where publicKey is BASE64 encoded

RSA encrypt a string from PEM public key in dotnet core

I'm trying to encrypt a string using a PEM public key file in dotnet core (1.1) and my question is: How do I do this?
I thought this would simply be a case of:
var cert = new X509Certificate2("path_to_public_key.pem");
using (var rsa = cert.GetRSAPublicKey())
{
// encrypt here
}
However, when I try to new up the certificate I get the following error:
error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error
The PEM file looks like this:
-----BEGIN PUBLIC KEY-----
... ANBgkqhkiG9w0BAQEFA ...
(loads more text)
-----END PUBLIC KEY-----
I've checked the pem file and there are no extraneous ^M characters anywhere (as from a suggest cause of the error here).
(I'm on macOS Sierra if that makes any difference)
Any help would be greatly appreciated!
Artjom B's comment sent me down the right path. A public key is indeed not a certificate.
Solution came from this excellent post.
For dotnet core (which doesn't have a RSACryptoServiceProvider class) I made a couple of minor modifications. You can return an RSAParameters object from GetRSAProviderFromPemFile, you can then use that like:
using (var rsa = RSA.Create()
{
rsa.ImportParameters(GetRSAProviderFromPemFile("path_to_pem.pem"));
var encrypted = rsa.Encrypt( ... );
}

Getting BadPaddingException while doing a Sqoop import with encrypted password file

I encrypt file with openssl then put it on HDFS, I used AES/ECB, 128 bits and salt option, and with some research I find out openssl uses PKCS5 padding as default which are all defaults in CryptoFileLoader class. Here is my encryption process:
# echo -n "password" > .pw
# openssl enc -aes-128-ecb -salt -in .pw -out .pw.enc
# hdfs dfs -put .pw.enc /user/user1/
Sqoop version is 1.4.6
Command:
sqoop import \
-Dorg.apache.sqoop.credentials.loader.class=org.apache.sqoop.util.password.CryptoFileLoader \
-Dorg.apache.sqoop.credentials.loader.crypto.passphrase=sqoop \
--connect jdbc:oracle:thin:#host/database \
--username user1 \
--password-file /user/user1/.pw.enc \
--table db.table1 \
--hive-import \
--hive-overwrite \
--hive-table hivedb.table1 \
--hive-drop-import-delims
which gives:
17/03/08 15:10:37 WARN tool.BaseSqoopTool: Failed to load password file
java.io.IOException: Can't decrypt the password
at org.apache.sqoop.util.password.CryptoFileLoader.loadPassword(CryptoFileLoader.java:151)
at org.apache.sqoop.util.CredentialsUtil.fetchPasswordFromLoader(CredentialsUtil.java:81)
at org.apache.sqoop.util.CredentialsUtil.fetchPassword(CredentialsUtil.java:66)
at org.apache.sqoop.tool.BaseSqoopTool.applyCredentialsOptions(BaseSqoopTool.java:1042)
at org.apache.sqoop.tool.BaseSqoopTool.applyCommonOptions(BaseSqoopTool.java:997)
at org.apache.sqoop.tool.ImportTool.applyOptions(ImportTool.java:875)
at org.apache.sqoop.tool.SqoopTool.parseArguments(SqoopTool.java:435)
at org.apache.sqoop.Sqoop.run(Sqoop.java:131)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:179)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:218)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:227)
at org.apache.sqoop.Sqoop.main(Sqoop.java:236)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
at javax.crypto.Cipher.doFinal(Cipher.java:2165)
at org.apache.sqoop.util.password.CryptoFileLoader.loadPassword(CryptoFileLoader.java:149)
... 12 more
Error while loading password file: Can't decrypt the password
I tried manually giving the other CryptoFileLoader parameters too and also passing local file to the --password-file .
I can decrypt the file back successfully with openssl. I can't decrypt with Java program(?)
I saw there is an issue with padding but I didn't know what it is and how to encrypt the file with a certain padding method or whatever else to do, I'm not experienced with encryption.
There is also org.apache.sqoop.credentials.loader.crypto.iterations parameter in the class which indicates number of PBKDF2 iterations but I don't know if it changes anything.
Thanks for any help.
I am not expert with Sqoop and Hadoop but starting from your exception
CryptoFileLoader.loadPassword(CryptoFileLoader.java:151)
I gave a look at the source code of CryptoFileLoader.java
It seems to me that things are a bit different from what you do: the password is stored in an encrypted file using the PBKDF2 algorithm, which is not equivalent to apply AES-128-ECB. From wikipedia:
PBKDF2 applies a pseudorandom function, such as hash-based message authentication code (HMAC), to the input password or passphrase along with a salt value and repeats the process many times to produce a derived key, which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult, and is known as key stretching.
There is no way to do PBKDF2 from Openssl command line. I made a small test using Java, it could be an alternative
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
public class Test {
/*Default is AES in electronic code book with padding.*/
private static String DEFAULT_ALG = "AES/ECB/PKCS5Padding";
/*Default salt is not much secure, use your own!*/
private static String DEFAULT_SALT = "SALT";
/*Iterate 10000 times by default.*/
private static int DEFAULT_ITERATIONS = 10000;
/*One of valid key sizes for default algorithm (AES).*/
private static int DEFAULT_KEY_LEN = 128;
public static void main(String[] args) throws IOException {
String inputFileName = "C:\\temp\\in.txt"; /*Enter your input (plain) file path */
String outputFileName = "C:\\temp\\out.bin"; /*Enter your output (encrypted) file path */
String passPhrase = "mypassphrase"; /*Enter your passphrase */
String salt = DEFAULT_SALT;
String alg = DEFAULT_ALG;
int iterations = DEFAULT_ITERATIONS;
int keyLen = DEFAULT_KEY_LEN;
SecretKeyFactory factory = null;
try {
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
} catch (NoSuchAlgorithmException e) {
throw new IOException("Can't load SecretKeyFactory", e);
}
SecretKeySpec key = null;
try {
String algOnly = alg.split("/")[0];
key = new SecretKeySpec(
factory.generateSecret(
new PBEKeySpec(passPhrase.toCharArray(), salt.getBytes(), iterations, keyLen)).getEncoded(),
algOnly);
} catch (Exception e) {
throw new IOException("Can't generate secret key", e);
}
Cipher crypto = null;
try {
crypto = Cipher.getInstance(alg);
} catch (Exception e) {
throw new IOException("Can't initialize the decryptor", e);
}
Path inputFileLocation = Paths.get(inputFileName);
byte[] decrypted = Files.readAllBytes(inputFileLocation);
byte[] encrypted;
try {
crypto.init(Cipher.ENCRYPT_MODE, key);
encrypted = crypto.doFinal(decrypted);
} catch (Exception e) {
throw new IOException("Can't decrypt the password", e);
}
Path outputFileLocation = Paths.get(outputFileName);
Files.write(outputFileLocation, encrypted);
}
}
As in Simone's answer - there is a difference in the encryption algorithm between openssl and java implementation. That is why you can decrypt using openssl with no problem (as it is invoking its own (different) algorithm again).
After much digging I found this answer from (Dave Thompson) which states:
Short answer: what openssl enc (without -K for raw) uses is not PBKDF2; it is almost PBKDF1, with iteration count 1.
It seems that there are two ways round this issue, either:
a) Find something in java that can decrypt what openssl is doing - there is a java library 'BouncyCastle' referenced in a post inside this answer (if you are happy using that instead of standard CryptoFile) where they have implemented the exact same algorithm that openssl is using.
or
b) Find some other command line utility to use instead of openssl that implements PBKDF2. A number of implementations in different languages are referenced in the nabble.com posting also mentioned.
(Due credit to Dave for the key observation quoted)

Encrypt string in JavaScript and decrypt in PHP with RSA technique

I am trying to encrypt some text in JavaScript and then send it to PHP (etc: with Ajax) to decrypt it there and save it (etc: In MySQL).
Here is my code so far:
In JavaScript:
I am using this library for the encryption:
http://travistidwell.com/blog/2013/02/15/a-better-library-for-javascript-asymmetrical-rsa-encryption/
function ConvertToURL(data) {
// Converts data to URL friendly form
// etc: Replaces '+', '/', '=' with 'plus', 'slash', 'equal'
};
function AjaxOrder(data) {
// Sends data in PHP with Ajax
}
var publicKey = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlOJu6TyygqxfWT7eLtGDwajtN
FOb9I5XRb6khyfD1Yt3YiCgQWMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76
xFxdU6jE0NQ+Z+zEdhUTooNRaY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4
gwQco1KRMDSmXSMkDwIDAQAB
-----END PUBLIC KEY-----';
var encrypt = new JSEncrypt();
encrypt.setPublicKey(publicKey);
var encrypted = encrypt.encrypt('Text to send.');
*// And now I am sending the encrypted text with some Ajax function*
AjaxOrder(ConvertToURL(encrypted));
In PHP:
$dataPost = $_POST('dt');
function ConvertFromURL($data) {
// Converts $data to original form
// etc: Replaces 'plus', 'slash', 'equal' with '+', '/', '='
}
function ReturnData($data) {
// Sends $data back in JavaScript as an answer to Ajax
}
$privateKey = '-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDlOJu6TyygqxfWT7eLtGDwajtNFOb9I5XRb6khyfD1Yt3YiCgQ
WMNW649887VGJiGr/L5i2osbl8C9+WJTeucF+S76xFxdU6jE0NQ+Z+zEdhUTooNR
aY5nZiu5PgDB0ED/ZKBUSLKL7eibMxZtMlUDHjm4gwQco1KRMDSmXSMkDwIDAQAB
AoGAfY9LpnuWK5Bs50UVep5c93SJdUi82u7yMx4iHFMc/Z2hfenfYEzu+57fI4fv
xTQ//5DbzRR/XKb8ulNv6+CHyPF31xk7YOBfkGI8qjLoq06V+FyBfDSwL8KbLyeH
m7KUZnLNQbk8yGLzB3iYKkRHlmUanQGaNMIJziWOkN+N9dECQQD0ONYRNZeuM8zd
8XJTSdcIX4a3gy3GGCJxOzv16XHxD03GW6UNLmfPwenKu+cdrQeaqEixrCejXdAF
z/7+BSMpAkEA8EaSOeP5Xr3ZrbiKzi6TGMwHMvC7HdJxaBJbVRfApFrE0/mPwmP5
rN7QwjrMY+0+AbXcm8mRQyQ1+IGEembsdwJBAN6az8Rv7QnD/YBvi52POIlRSSIM
V7SwWvSK4WSMnGb1ZBbhgdg57DXaspcwHsFV7hByQ5BvMtIduHcT14ECfcECQATe
aTgjFnqE/lQ22Rk0eGaYO80cc643BXVGafNfd9fcvwBMnk0iGX0XRsOozVt5Azil
psLBYuApa66NcVHJpCECQQDTjI2AQhFc1yRnCU/YgDnSpJVm1nASoRUnU8Jfm3Oz
uku7JUXcVpt08DFSceCEX9unCuMcT72rAQlLpdZir876
-----END RSA PRIVATE KEY-----';
openssl_private_decrypt(ConvertFromURL($dataPost), $decryptedWord, $privateKey);
ReturnData(base64_encode($decryptedWord));
Now the answer from PHP is empty every time. Any ideas to make this work?
Thank you for your time!
Use HTTPS.
What you are doing will never be able to protect you against active attacks (MitM) since you don't have any trust anchors, and it is very likely that you will make some stupid mistake that will make it insecure.
Either way, you cannot encrypt more than a few hundred bytes directly with RSA. Thus, you will have to securely generate a random symmetric key (doing that properly in JavaScript is not easy), encrypt the data with it using a secure symmetric cipher (e.g. AES) in a secure block cipher mode, then encrypt the symmetric key with RSA. Learning how to do it "properly" will take you much more time than really doing it properly, and that is, configuring SSL.

Resources