Implement sign with digital certificate on spring based web application - java

I have spring mvc based web application. One of the use cases requires a customer to digitally sign the information that he provides in a form . This signature then gets embedded into a PDF that will be generated on confirmation. How can I implement this in secure manner.
Currently I request the customer to download the PDF and sign it it offline and then upload it again as I do not want them to upload their private keys to the server
Could you please recommend a better approach for the same

The user could provide his private key in the form but it never gets send to the Server. Instead all the other fields of the form are sent to the server, the server then sends back the SHA hash of the generated PDF. Now this hash can be signed locally and the resulting signature can be sent back again to the server and be attached to the PDF.
However most users would never provide their private key in any online form and additionally it is not that easy to create a digital signature inside the form.
So instead you can go for a partial approach where the user just has to sign the SHA hash of the PDF and paste its signature on the next page of the form. So now download / upload is required. I would still make the download of the PDF optional so the user can check if the hash is valid.

Related

How to secure web services coming from only android app to server without login

This kind of question is already ask for IOS
How To Secure Web Service Without Login
but still I am not able to find the solution to make the web service secure without user authentication.
I have a web service made specially for android app as of now. I want that all the api hit should be only from my android app to the server. No one hack it and hits the api from restclient or postman.
How server will identify that request is coming from android app explictly the developed one and respond accordingly.
Method 1
I thought to do generate an api key and send that api key in request header which can be verified at server end. If key matches then server can assume the request is coming from whitelisted android app. But problem is that key has to be present inside android app which can be easily decompiled and can be hacked. Attacker may send api request directly from there app/web/ios rest client after obtaining the key .
Method 2
Api key can be easily stolen even kept in sharedprefernce. So i kept that in native code using jni which can not be decompiled, but that code can be dessembled and key can be read from there. So keeping the key within apk is unsecure. So this approach failed.
Method 3
I thought not to keep the original key inside app initially. but to use Asymmetric Keys. Private key was kept at server and encrypted key which got generated from public key was kept in android app.
API is called with input as encrypted key and server decrypts API key using private key and returns that key in response. that key is kept in the application scope and for subsequent request that key is sent in headers. So from now request becomes unsecured as original key is not known to attacker. but problem comes here
that
encrypted key + 1st api is exposed in the apk
Hacker will call the Api sending encrypted key along with url and get the actual key in response then that key can be used anywhere. So question is how to secure it so that no one can exploit the resources without login. I have to ensure that hit is coming from app only.
Method 4 It required login with google providing JWT Id token which can be easily verified at server end. but I dont want user to login with google. Just to know request is coming from android app only.
I'm afraid the only possible secure option is option 4.
In any case android app can be easily hacked without having 3rd party service that verifies correctness of the token.You don't have a choice.

How to exchange encryption keys with the customer?

My Java app needs to handle encrypted files. This is the workflow:
Customer encrypts files (RSA encryption for example) and uploads them to Amazon S3.
My Java app picks up the files from AS3.
My Java app decrypts the files.
My Java app creates other files using decrypted ones.
My Java app encrypts new files with different key and uploads to AS3.
Customer picks up the files.
Customer decrypts the files.
Amazon S3 provides the Java classes for download/upload, decryption/encryption. This API takes as input java.security.KeyPair. I am unsure how the customer should supply the key to My Java app, so that the app can get the key as java.security.KeyPair?
What would be the proper way to exchange the keys between Customer and App? Which key file format could be used?
Ussually, assymmetric encryption/decryption works like this:
You generate a private/public key pair. The private key should be held secret and should not be sent around etc. The public key can be given to the customer without security concerns.
Now the customer encrypts his files with this public key. The encrypted file can only be decrypted with the private key. So the user can send the file to you (over Amazon S3 in your case).
You receive the file and decrypt it with your private key.
Now you have got a file from the customer. To be able to send back encrypted messages, you need another public/private key pair. This time, the customer must be the only one knowing the private key. He can - for instance - put the public key in his file that he has sent to you. Anyway, somehow you need to get a public key from him. With that key, you encrypt your files and send them to Amazon S3. The user picks them up and decrypts them with his private key.
So, the customer must not give you a java.security.KeyPair, because those contain the private key. It's unsafe to send the private key. But he can send you the public key as a java.security.PublicKey. I think the best way would be to send it to you either within the file he supplies anyway, or within a separate file that he uploads at the same time and besides the supplied file.
The problem is that you don't have a method of distributing trust yet. Fortunately there is one that works reasonably well: TLS. TLS certificates are stored within the browser (and in the JRE, if you require a thick client instead).
Your key pair should be generated locally (or on a secured machine and imported). The private key should be kept safe the whole time. The customer connects to your site using TLS, and downloads your public key. Then the customer uploads the public key of his key pair. This can be performed during some setup/configuration phase.
Now the customer can encrypt files for you, and you can encrypt files for the customer. Note that TLS already provides encryption (confidentiality). So what you have gained is that files are protected during storage, after they have been transported. Once you have trust in the public key (and a trustworthy system) you could send files over plain HTTP.
Adding a signature is pretty important, otherwise anybody can replace the files in storage. Some audit logging is probably required as well, otherwise files may be removed.
Other schemes are possible (I prefer a PGP scheme for file encryption/decryption), but they require out of band communication of the keys. Note that this is just the basic scheme, there are a lot of pitfalls, but working out a specific security architecture for you application is clearly off topic.

How to encrypt data at client side using eToken

I am going to develop an application with Spring framework and JSP as follows:
1) When the client enters any text and presses encrypt button, the data should be encrypted at the client side, but that encryption should be done using eToken.
2) When the client uploads any file it should be stored in encrypted format in a database.
For that I searched on google but didn't find any helpful resources. We are using eToken that contains a key pair using the RSA algorithm. My problem is how to encrypt and decrypt data and files at the client side using eToken?
I am stuck here, please help me ASAP. Thanks.
Assuming that you want to do this via browser, you would need to have an ActiveX or Java applet, which will do the job. The task can not be accomplished using client-side javascript.
We developed similar solution in our SecureBlackbox product, though it works for signing at the moment (we couldn't imagine a real-life use case that would require encryption).
JFYI: To do encryption you don't need a private key but only a public key. Public key can be exported from the token to the computer.

Jersey Web Services Security Question

I am building a public facing REST application for clients to access. In trying to develop security for it, I looked at how AWS handles their REST authentication using an access key and secret key to sign the message before sending to the AWS server. So I coded an example with Jersey, JSP, and javascript (jsonp) to test, and it seems to work ok.
1.) On page load the JSP takes the client's access key and date/time (converted to EPOCH) and writes out to the page. It also takes those two pieces of information and combines them with the client's unique secret key via HMAC-SHA1.
2.) When I execute the JQuery ajax request, I pass in all three pieces of information.
user access key
date/time (EPOCH)
signed message
3.) On the Jersey side I take the access key and date/time and check a database for the users secret key. Then I perform my own HMAC-SHA1 signature and compare that to the signed message from the user submitted signed message. If they match, then allow them to use our web service. I also check the date/time and only accept messages signed within the last 15 minutes.
My question is, is this secure enough?
This isn't a complete answer, but I don't have the points to just comment quite yet. I would add to your security a salt on the server side. Please see this article for a good discussion on hashing using Master Keys and salts.

Make two servers talk to each other

I have application written in GWT and hosted on Google AppEngine/Java. In this application user will have an option to upload video/audio/text file to the server. Those files could be big, up to 1gb or so and because GAE/J does not support large file I have to use another server to store those files. This would be easy to implement if there was no cross-domain security feature in browsers. So, what I'm thinking is to make GAE Server talk to my server (Glassfish or any other java servers if needed) to tell url to the file and if possible send status of uploaded file (how many percent was uploaded) so I can show status on clients screen. Here is what I'm thinking to do.
When user loads GWT page that is stored on GAE/J he/she will upload file to my server, then my server will send response back to GAE and GAE will send response to the client.
If this scenario is possible what would be the best way to implement GAE to Glassfish conversation?
Actually before that maybe you can try using first approach via by-passing cross-domain security of browsers using iframe. There are some ready to use components for this but for your problem which of them can be usable I don't know. Just google for these components...
Doing it the original way you suggested use URL Fetch Service
The down side to doing it the other way is that you introduce dependencies on multiple sites inside your web pages.
The downside of using the URL Fetch Service is that you have to pay by number of bytes transferred after you have reached the free quota.
One option would be to wait - the blobstore limit won't always be 50MB!
If you're in a hurry, though, I would suggest an approach like the following:
Have your App Engine app generate a signed token that signifies the user has permission to upload a file. The token should include the current date and time, the user's user ID, the maximum file size, and any other relevant information, and should be signed using HMAC-SHA1 with a secret key that your App Engine app and your server both know.
Return a form to the user that POSTs to a URL on your blob hosting server, and embeds the token you generated in step 1. If you want progress notifications, you can use a tool like plupload, and serve the form in an IFrame served by your upload server.
When the user uploads the file to your server, the server should return a redirect back to your App Engine app, with a new token embedded in the redirect URL. That token, again signed with a common secret, contains the ID of the newly uploaded file.
When your App Engine app receives a request for the redirect URL, it knows the upload was completed, and can record the new file's ID etc in the datastore.
Alternately, you can use Amazon's S3, which already supports all this with its HTML Form support.

Categories

Resources