I have a Mobile App (iPhone and Android) which allows user to login to his account, change prefs etc...
I want to add a new feature where the user can buy products through his device or upgrade his service. Everything will run from the device and I want to make each transactions the user make it syncs to the web server.
I have HTTPS setup on my server. I would like to know if:
It is a good practice? or should I simply tell the user to use our website
If "yes", is HTTPS alone good to process these transactions?
Thanks
yes it's a good practice.
first of all ALWAYS use HTTPS.
make sure your certificate is valid and trusted.
for iphone:
iPhone: HTTPS client cert authentication
https://discussions.apple.com/thread/1652697?start=0&tstart=0
for android:
Trusting all certificates using HttpClient over HTTPS
Accepting a certificate for HTTPs on Android
second encrypt your data.
any encryption algorithm or rsa encryption will do the trick.
passing data using GET/POST should not be sent in plain text like: ?user=myuser&pass=mypass. instead use something like ?h28JduDak30fT1pfgmSnShNms762023lflsfdj2h4J. then on your server you simply have to decrypt it using a salt only your phone and the server knows.
example code for iphone:
NSString *encrypteddata =[NSString stringWithFormat:#"key=enryptedstring"];
NSData *data = [encrypteddata dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *datalen = [NSString stringWithFormat:#"%d", [data length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"https://yourserver:443/loginscript"]]; //:443 very importantz
[request setHTTPMethod:#"POST"];
[request setValue:datalen forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:data];
similar idea for android
then on your server you can decrypt $_POST['key'] and do your login logic (or others)
here's more resource that will help you:
iPhone + sending data from iPhone to server as XML format
iPhone: HTTPS client cert authentication
note:
for android you shoud take a look at the HTTPComponents
read more
http://www.javamex.com/tutorials/cryptography/rsa_encryption.shtml
http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-receive-data-from-the-server-in-iphone/
Related
I'm new to security so some of the terms might be used incorrectly:
When I create a socket connection using SSL_connect, the server should send back the entire certificate chain so that the authenticity of the server can be verified.
For this to happen, the server needs to be configured accordingly.
If the server doesn't send back the entire certificate chain and the intermediate certificate isn't in the client certificate store, the authenticity can't be verified. This results in the behavior experienced here in which FireFox regards a website as unsafe.
I've also read that some browsers are able to attain the intermediate certificate automatically. However, OpenSSL doesn't behavior like this, at least by default.
I've also been told that some (maybe all) intermediate certificates have been installed in Windows certificate stores since some Windows update was rolled out a few years ago.
I would like to view the certificates returned by the server to verify that I'm getting back the entire certificate chain. Here's what I've tried:
I'm using SSLv3_method.
SSL_CTX_set_verify is set using SSL_VERIFY_NONE.
After SSL_connect I use SSL_get_peer_cert_chain to get access to the certificate chain.
Consider:
STACK_OF(X509)* certificateChain = SSL_get_peer_cert_chain(ssl);
while (char* stackCertificate = sk_pop(certificateChain))
{
X509* certificate = (X509*)stackCertificate;
}
Is this the correct way to get the certificate chain? Is my understanding of the situation correct? Is there perhaps a better way to do this?
Thank you for your time and contribution.
The following code snippet is based off code in s_client:
SSL* ssl = ...;
STACK_OF(X509)* certCollection = SSL_get_peer_cert_chain(ssl);
for (size_t i = 0; i < sk_X509_num(certCollection); i++)
{
X509* cert = sk_X509_value(certCollection, i);
...
}
As far as I understand, an SSL session must have been created otherwise SSL_get_peer_cert_chain will return null. Additionally I haven't found any evidence to contradict the list I noted in my question.
Perhaps an easier alternative would be to use the command line tool (downloaded from here):
openssl s_client -connect {server}:{port} -ssl3
I'm having a weird problem with a JSF application I'm currently working on. It seems like there are two parts of my programm which are colliding.
There are two parts:
the "banking" functionality
the mail functionality
The relevant part of the banking functionality (It's a fake bank just for this exercise):
String path = FacesContext.getCurrentInstance().getExternalContext() .getRealPath("/") + "/WEB-INF/sec/certs.jks";
ErrorHandler.trace(path);
System.setProperty("javax.net.ssl.trustStore", path);
Here it's setting the Trust Store with the certificate for the bank server.
The mail part looks like this:
Properties props = new Properties();
props.put("mail.smtp.auth", this.smtpServer.isAuthenticated());
props.put("mail.smtp.starttls.enable", this.smtpServer.isTls());
props.put("mail.smtp.host", this.smtpServer.getHostaddr());
props.put("mail.smtp.port", this.smtpServer.getPort());
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.debug", "true");
final String username = this.smtpServer.getUsername();
final String password = this.smtpServer.getPassword();
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
session.setDebug(true);
One way to reproduce the problem:
The problem I'm facing is that if I start the application and, for example, use the "change mail" functionality I'll get my notification mail immediately. No problem there. Then I'll try to buy a product thus triggering the bank functionality.
That's where the problem shows up:
Communication Error: javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
- with linked exception:
[javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]
Another way to reproduce the problem:
Now let's say I restart my application and try to order something, this time it'll work but the mail functionality is broken with this error message:
DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL true
TRACE Error Could not connect to SMTP host: smtp.gmail.com, port: 465
Bottom line:
If I trigger bank and then mail -> mail not working
If I trigger mail and then bank -> bank not working
Anyone who could find a problem there?
Thank you!
Your "banking functionality" is changing the trust store. That new trust store needs to have the certificates necessary to validate the SSL connection with your mail server. You can initialize your trust store with all the CA certificates from the JDK default trust store, or you can add just the specific certificate for your mail server - see the InstallCert program. Finally, you can configure JavaMail to use a separate trust store, or change your banking functionality to use a trust store explicitly rather than overriding the default trust store; those are probably more complicated.
The problem was, that the mail functionality was working if there's no trustStore set (because it's using the system's default trustStore which is located in:
/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre/lib/security/cacerts
on a Mac.
The banking functionality is using it's own certificate which was located in:
MyProject/.../WEB-INF/sec/certs.jks
Every time the JavaMail tried to authenticate to Google's SMTP server it tried to use the certs.jks trustStore even though I unset the trustStore property the banking functionality set in the mail method.
Fix:
At the beginning of the mail method:
String path = FacesContext.getCurrentInstance().getExternalContext()
.getRealPath("/")
+ "WEB-INF/sec/certs.jks";
System.setProperty("javax.net.ssl.trustStore", path);
Import the default cacerts keyStore into our own custom keyStore:
keytool -importkeystore -srckeystore certs.jks -destkeystore cacerts
I have a WebAPI built using ASP.NET MVC4. It is a simple API for getting data (simple HTTP GET requests). The API is stable and has been working with our mobile (MonoTouch) app for quite some time. Now we're putting ForeFront UAG in front of the API (simply changed web.config to use windows auth. Testing the security and API through a browser e.g. Chrome, and the UAG login is presented (when hitting API first time). Enter your credentials and then you get the data back for the API GET request. All what you'd expect. Now, from .NET code (no browser) I want to do the same thing. I've seen examples accessing SharePoint programmatically and some windows phone stuff, but none of them seem to work for ASP.NET MVC4 WebApi calls from just regular old .NET code (which I'll eventually use in MonoTouch).
Anyone have an example of how to Authenticate and then make HTTP GET request successfully through UAG to an ASP.NET MVC4 WebApi?
I don't have the disposal over a ForeFront UAG so I can't test this. But in general you have a few options. The samples are snippets and some code is left out for readability.
WebClient / HttpWebRquest
CredentialCache credentials = new CredentialCache();
credentials.Add(new Uri(url), "NTLM", new NetworkCredential(userName, password, domain));
//WebClient
var webClient = new WebClient();
webClient.Credentials = credentials;
//HttpWebRequest
var request = HttpWebRequest.Create(url);
request.Credentials = credentials
HttpClient
WebRequestHandler clientHandler = new WebRequestHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.AllowPipelining = true;
clientHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
ProgressMessageHandler progress = new ProgressMessageHandler();
httpClient = HttpClientFactory.Create(clientHandler, progress);
You have also the options of using third party libraries to get this job done, like RestSharp or Service Stack.
Personally I make use of RestSharp because of the ease of use and serializing/deserializing capabilities.
I'm trying to figure out what iOS' policy is when verifying certificates using Security.Framework regarding revocation of certificates.
I cannot find information about this in the docs for iOS.
In the context of an iPad project I'm working on at the moment, there is reason to demand checking revocation status for some certs. Anyone ideas on how to force CRL / OCSP checking during cert verification using Security.Framework? Or do I need to "fall back" to OpenSSL to accomplish this?
It seems that also on Mac OS X 10.6 CRL / OCSP checks are done optionally and have to be turned on manually through Keychain Access.
Martijn
I have an answer to this question by Apple guys, I posted the full answer here:
Details on SSL/TLS certificate revocation mechanisms on iOS
To sum it up, there are several things to keep in mind for OCSP implementation on iOS:
OCSP policy cannot be configured at this moment
it works for the EV certificates only
high-level stuff, such as NSURLConnection or UIWebView use TLS security policy, which uses OCSP
SecTrustEvaluate is a blocking network operation
it works the "best attempt" - if OCSP server cannot be contacted, the trust evaluation will not fail
I just did this on iOS in GCDAsyncSocket.
For a given SecTrustRef trust;
do this
SecPolicyRef policy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod)
SecTrustSetPolicies(trust, policy);
SecTrustResultType trustResultType = kSecTrustResultInvalid;
OSStatus status = SecTrustEvaluate(trust, &trustResultType);
if (status == errSecSuccess && trustResultType == kSecTrustResultProceed)
{
//good!
}
else
{
//not good
}
//edit to check the trustResultType
I was able to enable CRL checking for a SecTrustRef object on iOS 10:
SecTrustRef trust = ...; // from TLS challenge
CFArrayRef oldPolicies;
SecTrustCopyPolicies(trust, &oldPolicies);
SecPolicyRef revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCRLMethod);
NSArray *newPolicies = [(__bridge NSArray *)oldPolicies arrayByAddingObject(__bridge id)revocationPolicy];
CFRelease(oldPolicies);
SecTrustSetPolicies(trust, (__bridge CFArrayRef)newPolicies);
SecTrustSetNetworkFetchAllowed(trust, true);
// Check the trust object
SecTrustResult result = kSecTrustResultInvalid;
SecTrustEvaluate(trust, &result);
// cert revoked -> kSecTrustResultRecoverableTrustFailure
Calling SecTrustSetNetworkFetchAllowed was key. Without that call, SecTrustEvaluate returned kSecTrustResultUnspecified instead.
I'm trying to access the files on a SharePoint-server(WOSS, 12.0.0.6421) through the WebServices but I can't sign in.
ListsService.Lists lists = new Lists();
lists.Credentials = new NetworkCredential("myusername", "mypassword", "mydomain");
lists.Url = "http://sharepointhost/_vti_bin/Lists.asmx";
XmlNode node = lists.GetListCollection();
return node.OuterXml;
But i get 401: unauthorized on GetListCollection, but the same username and password works perfectly when i access the sharepoint through a browser.
I checked the FAQ and found this: http://support.microsoft.com/default.aspx/kb/896861. But I'm not developing on the servering, I'm developing on another computer.
I found another thread which showed(http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/e115f790-fe8a-45e9-982b-21833ea01c7f) but when i use that solution I get "The HTTP request is unauthorized with client authentication scheme 'Ntlm'. The authentication header received from the server was 'NTLM'." which to me just seems even more confusing.
Try follwoing the steps mentioned in the link and this should solve your problem.
http://www.pentalogic.net/sharepoint-reminder/manual.aspx?Page=reminderservice%2fwssv3.htm
Tried and Tested - It worked for me.
HTH