I'm creating application that will create certificates for users. I want to mark somehow those certificates so that later I can search them in windows user certificate store by following categories:
application GUID (or name - I want to know that this cert is for my application)
certificate role (administrative certificate or user certificate)
user email
I know that for the last one I should use "E = J.Doe#mail.com" or OID number "1.2.840.113549.1.9.1 = J.Doe#mail.com"
But I don't know which OIDs to choose for application GUID and certificate role.
Or maybe I should use "Key Usage" field?
I don't know if it's important, but certificates will be used to authenticate to my application and to decrypt data in database.
Are there any standard ways to do it ?
Hmm... so what I'm thinking is that you plan to issue certificates to each user and you plan to make a different certificate for each application. So if you had 10 users using 3 applications each, you'd be making 30 certificates.
And then the certificate also describes the user's role within the application, and the users's email.
To tell you the truth, I wouldn't put all this information in a certificate. PKI is hard to provision - users generally have difficulties setting up certificates, and reissuing certificates is a pain. Generally, PKI deployment strategies try to minimize the number of certificates that must be issued, balancing that with risk.
The most typical scenario I've seen is that a user is given a single certificate which he uses to identify himself. The certificate includes the user's name, and his email. But it doesn't usually include the user's role or the specific application. Instead, this information is managed on an access control server, that is queried when the user accesses the system. That way, the roles and applications available to the user can be changed without having to reissue the certificate. Products like Active Directory, or Select Access do this sort of thing.
The reason to separate into a separate cetificate per usage is to specifically control some type of risk. For example, if a single user where doing a high-risk operation on one machin and a low risk operation on another, more potentially risky machine, there would be a case to have two certificates (one for each machine) so you could revoke the low-risk certificate without disabling the high risk functions. If you plan to store all the certificates on the same machine, it would be easier to only distribute one certificate per user.
That said - if you still see a need to issue 1 cert per user per application per role, I'd recommend finding a way to jam the application GUID, role and email into the Distinguished name.
You won't get much mileage out of Key Usage or Extended Key Usage - these have very specific value and I doubt that they will convey the information you want to describe. Also, they are used in particular ways by various other applications, so if you need to integrate with other things, that could get tricky.
OK, after few hours I came with something like this.
All Certificates will be recognized by Subject field.
For Administrator certificate it will look like this:
CN=<My application Name> Administrator,OU=Administrator,OU=<My application Name>,O=<My company Name>
and for users
E=<User email>,CN=<User email>,OU=User,OU=<My application Name>,O=<My company Name>
If someone has better idea, I'm open for suggestions :-)
Your task is a quite complex task. To solve it the best way is to put on work a little internal certification authority with openssl. Keep in mind that PKI assigned to the entities you referred the following rule:
Distinguished name: it is used to identify the user or entity to witch the certificate is issued. It's no properly correct to use it for identify two different entity within a single certificate: your user and the application. The two entities shuold be identify in two distinct place.
Key Usage is a bit field with 8 digit that defines the usage of the key. Every bit has its predefinited meaning and cannot be used for other purpose.
I suggest to you to:
Put the application GUID as x509 extension. You can assign and personal OIDs to that exension and query for it. If you OIDs is use internally you can utilize whatever value you want. If you plan to distribuite your certificat eyou can obtain your own OID from IANA
Put the mail in the fields subject alternative mail, as suggested by PKI.
For the aministrative or user you can add a second x509 extension or create a tree of certificate. The main CA certificate, the admin CA certificate and the user CA certificate. Every certificate for admin will be signed by the admin CA, every user certificate by the user CA.
Related
Most examples always take into consideration only one users using the system in the JWT/Flask tutorials. I want to understand this at a multi-user level but cannot find the correct resources.
Lets say we have the following secret key:
app.config['SECRET_KEY'] = 'randomkey'
Two Questions:
Would this key be the same for every user? if so, wouldn't this provide a security risk because if the key was stolen, anyone would have access to do whatever they want?
If it is not the same, how is the key stored on the server-side so it could be authenticated when requesting information? Would it be stored within the user's table under current token or something?
In this case, that key is the JWT signing key It could also be different from flask's secret key setting (see flask docs). It's not used for encryption so it's not intended to be a shared secret between server and users. Its role is to provide the server with a proof that the JWT content was generated by the server itself: it's a proof of integrity.
Having knowledge of that key means having the right to issue JWTs on behalf of the application, attackers could impersonate servers or make requests with some modified claims, eg pretending to be other users. This means that these keys are quite sensible from security perspective
Turns out that 1 app : 1 key, with some remarks
This key should theorically never change: if at time T1 KEY=x, a user could login in and receive a JWT signed with KEY=x. at T2 KEY=y, the user will invoke some API using the previous JWT and the server will try to verify(signature(payload , x) , y). So every user will be logged out automatically
Despite 1. It would be good to rotate the key. In this case the authentication system should save a buffer of old keys and use them to validate oldest JWT. Since a JWT should be short-lived, it could be useful set a rotation time grater than JWT expire time and just keep the last used key along with the current
This key is a secret and should be managed exactly as other secrets. Aside from terrible approaches like leaving it plaintext in the code/config, there are secret managers from cloud providers, or kubernetes secrets if you use the latter, as well as secret managers from configuration management tools (salt, ansible) or Hashicorp's Vault that is a specialized storage engine for sensible data. Anyway, it's more infra/security team concern if you are in a structured organization
The Stage
I'm working on a web application to enable trade of assets between different parties.
The different parties are known to me, and are not too many.
I record each transaction of an asset from one party to another in a database (sql server). I've stripped down database access as much as I can, and parties have to identify themselves by usernames and passwords to initiate transactions. Communication from web to api will of course be secure (https).
The Problem
These measures leaves me pretty confident that the stored transactions are authentic, but of course the parties of the transactions does not necessarily trust that I (or anyone else with sa password) haven't tampered with the data or created fake transactions.
My thinking
So I figure I need something to be able to prove the authenticity of such a transaction.
Maybe a signature from the party who is giving away their asset? A signature that I can store along with the signed transaction? In that case, the signer needs a private key and I think certificates is a way do this, right? I don't know of any way to access certificates installed on a computer from a web page though so the web page would have to launch a locally installed application to do the actual signing, because the locally installed application could access the certificate, and the signing party have trust in this application to sign the actual untampered-with transaction.
Is this a feasible solution?
How should certificates be distributed? I guess they should be issued from a CA that both I and the party trust?
Let’s say I have a contract between two parties published on the Web. I want both parties to be able to sign the contract to show they consent to the terms, the way they would with handwriting in real life. I have seen many TOS agreements online where this is done with just a check box, but I want to go a step further and enable each party to assert that the signature is theirs and not a forgery (somebody else checking the box for them).
Assuming the page is already served via HTTPS and username/password combos are not an option, which cryptographic technology is best suited for identity validation: PGP, SSL, or something else?
How might I do this using only HTML and a LAMP server on the other end, in such a way that the process is as automated as possible while still being secure? Code samples are obviously welcome but not necessary; I’m just trying to conceptualize it: do the contents of the contract have to be included in the signature? Do I have the users upload public keys or something? I’m no crypto expert so that’s where I get lost.
SSL is a transport security mechanism, it's not applicable.
You can use OpenPGP or you can use PKI (X.509 certificates and CMS format). These technologies let you sign the data twice or more times without invalidating previous signatures - this is done by using detached signatures.
The choice of what (PGP or PKI) to use is yours - these technologies can be used in similar scenarios, but have different ways to authenticate keys: in PGP user keys are signed by other users, while in PKI certificates are signed by certificate authorities, which is supposed to have more credibility.
When you "sign the document" using cryptographic signature, from technical point of view it's a hash of the document that is signed. The hash can be calculated on the server and sent to the client for signing, then the detached signature is transferred back to the server. So you can keep the document on the server, and private keys used for signing will not leave the client.
However, to do actual signing on the client, you need some module which will communicate with the server and do the job. You can't go with just a web browser - some browser plug-in is required. The reason is that Javascript "cryptography", even if it technically allowed access to client-side keys stored in files or on cryptographic devices, has certain conceptual flaws which make it almost useless. So you end up with using something more trusted and secure, i.e. signed applet or ActiveX control or Flash script.
Our company provides various security components, among which there are components and modules for distributed signing (including above mentioned plugins). These modules are for PKI operations (though in general we also have components for OpenPGP operations, these components don't support distributed signing at the moment).
And I should note, that "automation" here is possible to extent when the user chooses the certificate to use and clicks "sign" button (for example). You can't sign anything without user's explicit action. In some cases the user would also need to provide a PIN / password which protects a private key from being misused.
I'd like to make requests from an iphone app to a web service I've built. How can I verify that requests made to the web service come from my iphone app (or indeed any authorised source) and are not forged?
I have looked at basic auth over HTTPS but is baking credentials into an application secure?
This question isn't really iphone specific; I'd like to know how to protect and authenticate requests in general.
Authentication can be asserted by presenting something you know, something you have, something you are or a combination of the three.
The iPhone doesn't have retinal or fingerprint scanners, so there are no "something you are" options available.
Client certificates work well as a "something you have" token. Most smartcards work by signing a message with an embedded certificate. When a certificate is compromised, it can be put onto a Certificate Revocation List (CRL) referenced by the webservers. Obviously, you wouldn't want to put your app's embedded certificate in the CRL -- that would deny access to all your users. Instead, you'll want users to download individual certificates to their iPhone.
After that, it's a matter of monitoring for unusual behavior to find the bad actors and adding those certs to the CRL. Two dead giveaways would be clients who send too many requests at once or from too many different IPs in too short a time.
Login/password is a simple "something you know" token. Like certificates, login/password combinations can be compromised and similar monitoring can be set up to find inappropriate behavior. The difference is compromised accounts would be marked "blocked" rather than added to a CRL.
By requiring both a client certificate and a login/password you increase the amount of effort needed to compromise an account.
Of course, you must ensure only valid accounts are added to the database. If there is an automated way to create new accounts and corresponding client certificates, then that account creation server/process becomes the easiest way for bad actors to create viable, unauthorized accounts. Requiring a real person to sign-off on accounts removes the automation process, but means a disgruntled or corrupt employee could create invalid accounts. Requiring a second person to counter-sign the account makes it harder for a single person to be an inside threat.
In short, ensuring high integrity of the clients is a process that can be made arbitrarily complex and expensive. What tools and processes you decide to deploy as the authentication scheme has to be balanced by the value of what it is protecting.
In theory, if you want the connection to be secure, the best is to have the client sign their request using a certificate. There are multiple resources about this. Look for "client certificate" on Google.
This example from Sun is in Java, but the concept is similar whatever the language.
PS: obviously, this doesn't prevent you from using other authentication methods such as passwords, etc...
PPS: Keep in mind that if someone manages to extract the certificate from your application, you are screwed either way ;-). You can imagine a store providing an individual certificate to each app and invalidating the certificates that are compromised.
I'm building a solution consisting of an app and a server. Server provides some methods (json) and the app uses them. My aim is to make those API methods inaccessible to other clients. What is the best way to do so?
Should I take a look at certificates (to sign every outgoing request)? If yes, where do I start and what is the performance impact of doing so?
What are alternatives?
Put another way, you need a way to distinguish a valid client's request from an invalid client's request. That means the client needs to present credentials that demonstrate the request comes from a valid source.
SSL certificates are an excellent way to assert identity that can be validated. The validity of an SSL certificate can be confirmed if the certificate contains a valid signature created by another certificate known to be secure, a root cert. As noted in other answers an embedded certificate won't do the job because that certificate can be compromised by dissecting the app. Once it is compromised, you can't accept any requests presenting it, locking out all your users.
Instead of one embedded app cert, you need to issue a separate certificate to each valid user. To do that, you need to set up (or outsource to) a Certificate Authority and issue individual, signed certificates to valid clients. Some of these certificate will be compromised by the user -- either because they were hacked, careless or intentionally trying to defraud your service. You'll need to watch for these stolen certificates, place them on a certificate revocation list (CRL) and refuse service to these compromised certificates. Any web server is able to refuse a connection based on a CRL.
This doesn't solve the security issues, it just moves them out of the app. It is still possible for someone to create what appears to be a valid certificate through social engineering or by stealing your root certificate and manufacturing new signed certificates. (These are problems all PKI providers face.)
There will be a performance hit. How much of a hit depends on the number of requests from the app. The iPhone NSURLConnection class provides support for SSL client certificates and client certificates can be installed in the phone from an e-mail or authenticated web request. Managing the infrastructure to support the client certs will require more effort than coding it into the app.
Incidentally, voting down any answer you don't like creates a chilling effect in the community. You're not nearly as likely to get advice -- good or bad -- if you're going to take a whack at everyone's reputation score.
I will now freely admit that it's an interesting question, but I have no idea how it could be done.
Original answer:
Interesting question. Assuming people can't reverse-engineer the iPhone app, the only solution that comes to mind would be to sign requests with a public key, or some other secret known only to the application. By that, I mean adding an extra argument to every API call that is a hash of the destination URL and other arguments combined with a secret known only to your server and application.
To expand upon this: suppose your API call has arguments foo, bar and qux. I would add a signature argument, the value of which could be something as simple as sorting the other arguments by name, concatenating them with their values, adding a secret, and hashing the lot. Then on the server side, I would do the same thing (excepting the signature argument) and check that the hash matches the one we were given in the request.
Consider authenticated HTTP.
For a cheaper alternative, there's shared secret/hash scheme. The client and the server have a shared secret string of text. Upon request, the client hashes together (using MD5, or SHA1, or SHA something else - you choose) the request fields and the secret. The hash value is attached to the request - say, as another POST field.
The server does the same operation with the request and with its copy of the secret, then compares the hash values. If they don't match - service denied.
For added security, you may encrypt the hash with a RSA public key. The client has the public key, the server keeps the private key. The server decrypts the hash with the private key, then the same. I did that with a C++ WinMobile client and a PHP-based service - works like a charm. No experience with crypto on iPhone, though.
UPDATE: now that I think of it, if we assume that the attacker has complete control over the client (ahem jailbroken iPhone and a debugger), the problem, as formulated above, is not solvable in theory. After all, the attacker might use your bits to access the service. Reverse-engineer the executable, find the relevant functions and call them with desired data. Build some global state, if necessary. Alternatively, they can automate your UI, screen scraper style. Such is the sad state of affairs.