Where to store .pem file (private key) android java - java

I'm trying to create a JWT using a private key stored in a .PEM file. I understand private keys shouldn't be stored in the code and you can add keys to the global gradle.properties file to avoid exposing them but if I have a .PEM file how do I access it, in my code. from my local drive.
The yodlee documentation tells me to add the path below but how does this work?
public class ConfigurationParams {
public static final String iss = "135143514315321";
public static final String privateKeyFile = "/Users/bob/token/priv.pem";
}
The privateKeyFile path is passed through the file variable.
public class TokenManagement {
#RequiresApi(api = Build.VERSION_CODES.O)
static private String getKey(String file) {
String privKey;
try {
privKey = new String(Files.readAllBytes((Paths.get(file))));
} catch (IOException ex) {
privKey = null;
}
return privKey;
}
}

It seems more of an android related question. But if you are planning to have the key on the user's device then you should not do that.
All Yodlee APIs are IP restricted in production environment, and all API calls should be made from your server to Yodlee. Hence, you should store it at your server side not at the client side, if that's what you are trying to do.

Related

How to return a file from a controller inside an entity?

I tried to return .pfx certificate as bytearray
public class CertificateContainer {
private CertificateType certificateType;
private byte[] certificate;
private Map<String, String> authData;
}
converting into bytearray
FileUtils.readFileToByteArray(ResourceUtils.getFile(certificateType.getPathToCertificate()))
And the controller's return
#GetMapping
public ResponseEntity<CertificateContainer> getCertificate(#RequestParam CertificateType certificateType) {
return ok(certificateService.getCertificate(certificateType));
}
On a client's side, I'm getting String instead of bytes and adding it to an array
new ByteArrayInputStream(
certificateContainer.getCertificate().getBytes()
)
after that, adding into key store and getting exception "stream does not represent PKCS12 key store".
But if I add the same file from the client storage, it works properly. What I did wrong with transporting the file?

Storing Java Objects For Further Use in WebApp That Uses REST

I have a webapp which make REST call for respective functionalities.
Say, I have a webapp in which a user registers and a KeyValue pair is generated which is required for authentication during ssh. Now this KeyValue pair is unique.
And the other web page of the same application I want those KeyValue pair to be downloaded as a ppk file to ssh. "So that particular object is required".
So is there a way to store the object.
I do have a Postgres DB.
What are my possible options?
Edit: The Object I want to store, is a third-party implemented library JSch (which is an full implementation of SSH-2), so simple Key-Value pair might not be solution I guess!)
REST is stateless so is not possible to mantain it on the server side!
You can create a token that is the encryption of the couple key, value on the server side and send it to the client (browser).
The browser is responsible to mantain the token and send it to the server if needed.
The server can decrypt the token and retrieve the original key value couple.
This will grant you that the client can't access to the couple key value because it is encrypted in a manner that the client can't read it.
Note If you need to mantain those values only for a limited quantity of time you can encrypt in the token also a value corresponding to the creation of token or to last access to the token.
This technique is generally used to mantain "sessions" on client side in an application that use only REST calls, but needs to maintain informations related to the current user.
If you only want to store a single key/value pair, then you can store it in the session. If you want to store multiple pairs, it works similar, but you'd store a collection of pairs in the session. Have a look at HttpServletRequest.getSession() for details.
If you want to share the key/value pair across all sessions (other users, multiple browsers) and you only have a single web server, just use a static variable.
If you want to share the key/value pair across all sessions and you have multiple servers, then you'll have to store it in the database (unless you'd consider build some data exchange protocol between servers, but I doubt that would be the simplest thing you could do).
You should store the key value pair in DB. You can use redis for faster access to this pair similar to a cache and auto delete based on expiration time you want to set.
This is the same way data is cached by servers in sessions. Since REST APIs are dateless, you have this alternate which should work just fine.
As I wanted a key for ssh'ing into my machine which is provided by KeyPair Object of JSch. I did stored it in my database by serializable for future applications like this,
#Entity
#Table(name ="keypairs")
public class KeyPairDomain {
private Long id;
private String username;
private byte[] byteObject;
private KeyPair keypair;
public KeyPairDomain(KeyPair kpair, String username) {
super();
this.setUsername(username);
this.keypair = kpair;
}
#Transient
public KeyPair getKeypair() {
return keypair;
}
public void setKeypair(KeyPair complexObject) {
this.setKeypair(complexObject);
ByteArrayOutputStream baos;
ObjectOutputStream out;
baos = new ByteArrayOutputStream();
try {
out = new ObjectOutputStream(baos);
out.writeObject(complexObject);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
this.byteObject = baos.toByteArray();
}
#Column(columnDefinition = "bytea")
public byte[] getByteObject() {
return byteObject;
}
public void setByteObject(byte[] byteObject) {
ByteArrayInputStream bais;
ObjectInputStream in;
try {
bais = new ByteArrayInputStream(byteObject);
in = new ObjectInputStream(bais);
setKeypair((KeyPair) in.readObject());
in.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
this.byteObject = byteObject;
}
public String getUsername() {
return username;
}
#Column(name = "username")
public void setUsername(String username) {
this.username = username;
}
#Id
#GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
but I stored a ppk file in a tmp folder of any machine type. And when required I use that location to fetch that key.
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_OCTET_STREAM)
#POST
#Path("/getCredentials")
public Response getCredentials(HashMap<String, String> userDetails) {
String username = userDetails.get("username");
File homedir = new File(System.getProperty("user.home"));
File file = new File(homedir, "credentials/" + username + "/Key.ppk");
System.out.println("File Path: "+file.getAbsolutePath());
System.out.println("File Name: "+file.getName());
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=" +file.getName()).build();
}

How to read p12 file from system in Java?

In my application I make use of a p12 certificate file to encrypt traffic when talking to an API I am using.
For my production environment, I need to read these files off the system rather than from the application.
On Linux, how might I read these files off my system into my application into an InputStream just like I would from a resources directory in my application?
I am using Java.
I built a quick and dirty little class to show the opening of a relative .pfx (P12) that I created with keytools. Naturally, you can also look through different potential directories looking for the file, if there are a couple likely places for it to be.
The file structure looks like this:
./bin
./bin/Test.java
./bin/Test.class
./conf
./conf/myFile.pfx
Here's the test code:
import java.io.*;
import java.security.*;
class Test {
public static void main(String[] args) {
String pass = "password";
try {
File file = new File("../conf/myFile.pfx");
InputStream stream = new FileInputStream(file);
KeyStore store = KeyStore.getInstance("PKCS12");
store.load(stream, pass.toCharArray());
PrivateKey key = (PrivateKey)store.getKey("example", pass.toCharArray());
System.out.println("Success");
} catch (KeyStoreException kse) {
System.err.println("Error getting the key");
} catch (Exception e) {
System.err.println("Error opening the key file");
e.printStackTrace();
}
}
}

Create a public folder in internal storage

Sorry for my English, but I want to write in this file because in my opinion is the best.
Now my problem:
I want to create a folder in Internal storage to share with 2 application.
In my app, I downloaded an Apk from my server and I run it.
Before I used external storage and everything worked.
Now I want to use the internal storage for users that don't have an external storage.
I use this:
String folderPath = getFilesDir() + "Dir"
but when i try to run the Apk, it doesn't work, and I can't find this folder on my phone.
Thank you..
From this post :
Correct way:
Create a File for your desired directory (e.g., File path=new
File(getFilesDir(),"myfolder");)
Call mkdirs() on that File to create the directory if it does not exist
Create a File for the output file (e.g., File mypath=new File(path,"myfile.txt");)
Use standard Java I/O to write to that File (e.g., using new BufferedWriter(new FileWriter(mypath)))
Enjoy.
Also to create public file I use :
/**
* Context.MODE_PRIVATE will create the file (or replace a file of the same name) and make it private to your application.
* Other modes available are: MODE_APPEND, MODE_WORLD_READABLE, and MODE_WORLD_WRITEABLE.
*/
public static void createInternalFile(Context theContext, String theFileName, byte[] theData, int theMode)
{
FileOutputStream fos = null;
try {
fos = theContext.openFileOutput(theFileName, theMode);
fos.write(theData);
fos.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "[createInternalFile]" + e.getMessage());
} catch (IOException e) {
Log.e(TAG, "[createInternalFile]" + e.getMessage());
}
}
Just set theMode to MODE_WORLD_WRITEABLE or MODE_WORLD_READABLE (note they are deprecated from api lvl 17).
You can also use theContext.getDir(); but note what doc says :
Retrieve, creating if needed, a new directory in which the application can place its own custom data files. You can use the returned File object to create and access files in this directory. Note that files created through a File object will only be accessible by your own application; you can only set the mode of the entire directory, not of individual files.
Best wishes.
You can create a public into a existing system public folder, there is some public folder accessible from internal storage :
public static String DIRECTORY_MUSIC = "Music";
public static String DIRECTORY_PODCASTS = "Podcasts";
public static String DIRECTORY_RINGTONES = "Ringtones";
public static String DIRECTORY_ALARMS = "Alarms";
public static String DIRECTORY_NOTIFICATIONS = "Notifications";
public static String DIRECTORY_PICTURES = "Pictures";
public static String DIRECTORY_MOVIES = "Movies";
public static String DIRECTORY_DOWNLOADS = "Download";
public static String DIRECTORY_DCIM = "DCIM";
public static String DIRECTORY_DOCUMENTS = "Documents";
To create your folder, use this code :
File myDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "MyPublicFolder");
myDirectory.mkdir();
With this example, a public will be created in Documents and can be visible in any file's explorer app for Android.
try the below
File mydir = context.getDir("Newfolder", Context.MODE_PRIVATE); //Creating an internal dir;
if(!mydir.exists)
{
mydir.mkdirs();
}
This is what i have used and is working fine for me:
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File file = new File(extStorageDirectory, fileName);
File parent=file.getParentFile();
if(!parent.exists()){
parent.mkdirs();
}
This will create a new directory if not already present or use the existing if already present.

How to encrypt SOAP messages manually?

I use JBoss 4.2.3.GA. In previous task I've used base encryption mechanism which JBoss supports (WS-Security). I.e. I used keystore, truststore files for encryption and signing messages. As usually (in standard way) in jboss-wsse-* files were defined aliases of keys that must be used during crypt process. I used ws security configuration from JBoss in Action book.
That's Ok. Encryption works fine.
But in my current task I need to specify aliases for keys manually and dynamically.
Task description:
I have several profiles. In every profile can be specifiey alias of public key that must be used for encrypting message.
I have keystore containing private/public key of server and public keys of clients that will send message to server
I need get alias from profile and encrypt message (on client side) using public key specified by this alias.
So I need somehow to load data from keystore (it must resides in file system folder, i.e. outside ear file), get appropriate public key from it and then do encryption.
After that I need to send message to remote web service (server side) that has private keys for decryption.
Here I see several variants for server side logic: web service makes decryption using standard JBoss mechanism or I can do it manually loading keystore data and do decryption manually.
So the questions are about:
Is there a way to specify for JBoss the file system directory to load keystores from?
Can I specify alias for encryption for standard JBoss WSS mechanism to allow jboss to use this information in crypt process?
If I must to do manual encryption/decryption then How can I wrap several Java-objects into WS message and then encrypt it using necessary alias and how to send this message to remote web service manually?
I just don't know how to start, what framework to use and even is it necessary to use external (non JBoss) frameworks for this...
If possible you can use Axis2 and Rampart. I've successfully used them both in a similar situation.
Rampart is an axis2 module for handling security and it exposes an API that allows you to define the key store location and aliases that you want to use, thus allowing you to define it dynamically.
Axis2
Rampart
Sample code:
private static final String CONFIGURATION_CTX = "src/ctx";
private static final String KEYSTORE_TYPE = "org.apache.ws.security.crypto.merlin.keystore.type";
private static final String KEYSTORE_FILE = "org.apache.ws.security.crypto.merlin.file";
private static final String KEYSTORE_PWD = "org.apache.ws.security.crypto.merlin.keystore.password";
private static final String PROVIDER = "org.apache.ws.security.components.crypto.Merlin";
private static void engageRampartModules(Stub stub)
throws AxisFault, FileNotFoundException, XMLStreamException {
ServiceClient serviceClient = stub._getServiceClient();
engageAddressingModule(stub);
serviceClient.engageModule("rampart");
serviceClient.engageModule("rahas");
RampartConfig rampartConfig = prepareRampartConfig();
attachPolicy(stub,rampartConfig);
}
/**
* Sets all the required security properties.
* #return rampartConfig - an object containing rampart configurations
*/
private static RampartConfig prepareRampartConfig() {
String certAlias = "alias"; //The alias of the public key in the jks file
String keyStoreFile = "ctx/client.ks";
String keystorePassword = "pwd";
String userName = "youusename";
RampartConfig rampartConfig = new RampartConfig();
//Define properties for signing and encription
Properties merlinProp = new Properties();
merlinProp.put(KEYSTORE_TYPE, "JKS");
merlinProp.put(KEYSTORE_FILE,keyStoreFile);
merlinProp.put(KEYSTORE_PWD, keystorePassword);
CryptoConfig cryptoConfig = new CryptoConfig();
cryptoConfig.setProvider(PROVIDER);
cryptoConfig.setProp(merlinProp);
//Rampart configurations
rampartConfig.setUser(userName);
rampartConfig.setUserCertAlias(certAlias);
rampartConfig.setEncryptionUser(certAlias);
rampartConfig.setPwCbClass("com.callback.tests.PasswordCallbackHandler"); //Password Callbak class
rampartConfig.setSigCryptoConfig(cryptoConfig);
rampartConfig.setEncrCryptoConfig(cryptoConfig);
return rampartConfig;
}
/**
* attach the security policy to the stub.
* #param stub
* #param rampartConfig
* #throws XMLStreamException
* #throws FileNotFoundException
*/
private static void attachPolicy(Stub stub, RampartConfig rampartConfig) throws XMLStreamException, FileNotFoundException {
Policy policy = new Policy();
policy.addAssertion(rampartConfig);
stub._getServiceClient().getAxisService().getPolicySubject().attachPolicy(policy);
}
PasswordCallbackHandler:
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class PasswordCallbackHandler implements CallbackHandler {
// #Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];
String id = pwcb.getIdentifer();
switch (pwcb.getUsage()) {
case WSPasswordCallback.USERNAME_TOKEN: {
if (id.equals("pwd")) {
pwcb.setPassword("pwd");
}
}
}
}
}
}
1&2: Defining keystore for jboss:
<jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/ws-security/config
http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
<key-store-file>WEB-INF/wsse.keystore</key-store-file>
<key-store-password>jbossws</key-store-password>
<trust-store-file>WEB-INF/wsse.truststore</trust-store-file>
<trust-store-password>jbossws</trust-store-password>
<config>
<sign type="x509v3" alias="wsse"/>
<requires>
<signature/>
</requires>
</config>
</jboss-ws-security>
3: Encryption replacement (and manual too) example described here for axis2: http://www.javaranch.com/journal/2008/10/web-service-security-encryption-axis2.html

Categories