Can't understand why Encrypted Custom Fields are not rendered as
type="password" on the standard UI. The first time you input or later
if you change the content, it's just plain text.
Because they aren't password fields. You use it to store "masked" information. This helps with instant feedback so that the user can input the data correctly. For example, if I'm asking you for your SSN, you're going to tell me, and I'm going to read it back to you. If it were a literal password field, I would have to write it down, which is far riskier than simply showing it on the screen until I save.
If you come back to the edit screen, it is at least replaced by * -
but still exposing the length...
Again, this is for validation of input later. For example, you can choose to expose the last few characters, as in ****-****-****-9641. It gives you a feel for how much data is actually in there without actually exposing the data. Personally, I feel better knowing that after I enter a password, I can see that I entered the right number of characters correctly.
This odd behavior leads to very risky
side-effects, e. g. if you use it for passwords or other sensitive
data, it typically ends up in your browsers form-cache and may be
accidentally disclosed to people who look on your screen.
Salesforce dropped the ball on this one. I was going to say that autocomplete (HTML5 attribute) should be turned off (i.e. autocomplete="off") for the field, but it's not. I'm going to submit an idea for this, because that is indeed a security concern. Especially on Google Chrome where your auto-complete history is also synced across all your devices. Security risk nightmare if you're storing SSN, CC numbers, etc. In fact, now being aware of this, I'd recommend all organizations that care about potential risks to disable autocomplete on all browsers fairly immediately.
So a visualforce page seems to be required to fix this flaw? Or is it a feature?
It's supposed to be a feature. For example, you work in a call center that requires validation of the last 4 of the SSN. A normal user can see the last 4 characters without knowing the first 5 characters. This reduces risk for simple viewing; this question revolves more around data capture and not exposure, really. You sometimes need to be able to know this. As a further example, say you're storing credit card numbers, and a customer has five cards on record, and all the fields are totally obscured. Are you expected to re-enter all five cards when one expires? Is this reasonable?
As far as I see, the value of an encrypted fields may also be visible
to users that have the “View Encrypted Data” permission - which again
seems dangerous and most likely unwanted.
Usually, it's system administrators and employees with sufficient clearance, and this is primarily because they have a job function or responsibility that includes seeing that data in its decrypted form (e.g. data backups, performing background checks, etc). Again, don't give that permission to just any normal user, but do expose the last few characters if their job function requires it.
I think the values should never be exposed on the UI. If the data is
stored let's say as copy&paste provider for human beings (again bad
and badder), it should go directly or at least invisible into the
Again, sometimes it must be exposed, and there's no two ways about it. Clipboard support is spotty at best, so I'm not entirely surprised it's not restricted. Besides, if you really wanted to go down that road, you would have to ban screenshots, notebooks, etc. Again, with sensitive information, all employees/users that will handle the data must be vetted properly. Don't give them the keys to the kingdom if they only need the keys to the storage room.
Minimize risk/exposure, but realize that for some use cases, you must accept the risk as a normal cost of doing business. For example, I'm pretty sure that anything to do with credit must verify the birthdate and last four of the SSN of the party. You can't legally not do this.
But maybe this field type was designed for a different purpose and I
just have not figured out? Or it is just one of those aged parts of
I think this answer is already pretty detailed about it's intended use, but I'm going to keep going...
As a best practice to store login credentials would you use an
Encrypted Custom Fields or a text field and do-it-yourself encryption
using Apex Crypto Class?
Either or; pick your poison. On the one hand, if it were a true password field with only one entry, you could mistype it, and have to go through the whole mess again, since there's no double-entry for the field, unless you built two fields and used a validatin rule... On the other hand, roll-your-own encryption isn't much better in most cases. Why? Because the data has to be base-64 encoded, giving you a random string of characters to look at. You'll still be able to make an educated guess about the content, unless you also provide pseudo-random padding, etc. Also, you'd have to build an entire UI (Visualforce) to handle that one field. Is it worth it? Maybe, if at least for working around salesforce's huge blunder (above), but were that fixed, I would find little argument for building a UI unless you wanted instant validation of the input.
For which use-case you would use Encrypted Custom Fields?
Social Security Numbers and Credit Card Numbers are the usual case. Sometimes it's appropriate to store private keys in such a field (or roll your own encryption is tempting here). In some cases, I have seen passwords stored in there, and that may be okay. Also, I'd store oauth2 tokens in a pure-masked field (because the user will never see or handle the key, as it would be generated through salesforce-remote-party interaction with Visualforce).
Final Note: If you're worried about even your account being compromised, make yourself a new profile with all permissions except View Encrypted Data, create a spare administrator account, change your profile to the new custom profile, then deactivate the spare administrator account. This reduces casual data exposure from your account because of this default permission.