-
Notifications
You must be signed in to change notification settings - Fork 599
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make KeyType compatible with Android Keystore #586
Conversation
Android Keystore private keys do not implement PrivateKey since the raw key material is not available to applications. With this commit, sshj's KeyType correctly detects the algorithm associated with Android Keystore keys, which makes them usable for SSH authentication.
src/main/java/net/schmizz/sshj/common/ECDSAVariationsAdapter.java
Outdated
Show resolved
Hide resolved
I've merged master into this branch to fix the builds. |
I closed and re-opened to see whether this would trigger travis. Unfortunately, it didn't. |
I still need to remove travis :) Now with GH Actions travis is no longer needed... |
Thanks! Are you able to provide an estimate fow when 0.30.0 will be released? |
@FabianHenneke could you perhaps show how one could put ssh keys into Android Keystore please? that's something i could use in my app btw 0.30.0 was released |
It's actually quite simple, you just need to implement a |
thanks! |
i can't get this to work. my device is running Android 10. in gradle i'm using
i tried "importing" BC in a variety of ways, and stuff below are best case scenarios
any ideas as to what might be wrong? perhaps we can have a tiny example of Android + sshj + AKS? |
I would strongly recommend to generate keys within the Android Keystore, not import keys from the outside. If you want to protect an existing SSH key, consider wrapping it using the AndroidX Security library's Because I have never tried this myself, I unfortunately can't help you with the issues you are facing when importing keys.
This I might be able to help you with. The stack traces you provided seem to indicate that SSHJ is specifying the engine for its signature operations to be specifically BC, whereas the Keystore-backed keys require a different engine that should not be specified explicitly. With sshj 0.30.0, you should be able to work around this in the following way:
I implemented these steps here: https://github.com/android-password-store/Android-Password-Store/blob/8a4316067396e6a0a5490e727197cf843d3f4ec6/app/src/main/java/com/zeapo/pwdstore/git/sshj/SshjConfig.kt#L36-L57 |
thanks for trying to help!
it's a good idea, and we might implement it some day (low priority), but the ability to import existing keys is something our users expect so it better work
also a good idea, thanks. as i understand, the key material must be decrypted into memory in order for the key to perform actual crypto? but yeah, we should do it
i think i solved this somewhat, this code loads pkcs1 and pksc8 files only relying on BC. the trick is using
i tried your code and i still can't connect, except if i use a very nasty trick i tried running
and this error when connecting:
(on the sshd part, i get this:)
if i run my |
Yes, the contents of the decrypted file would be used to initialize a
This looks pretty good. The rule of thumb regarding the Android Keystore is that everything should work as long as no explicit provider is ever set anywhere.
You get this error because the SSHJ default config is not really usable without automatically registered BC. You will have to roll your own config. Ours can be found here for reference, just ignore the |
aha, i think i figured this part out! for the sake of testing, this works: SecurityUtils.setSecurityProvider("BC");
ssh = new SSHClient();
SecurityUtils.setSecurityProvider(null); this will require a lot of work, still. perhaps this would be best to put into another small thing. how do i specify the types of host keys that i have for the server? looking at firstMatch(this.getHostKeyAlgorithms(), other.getHostKeyAlgorithms()), and host keys come from public List<String> getHostKeyAlgorithms() {
return sig;
} and sig = Factory.Named.Util.getNames(config.getKeyAlgorithms()); but as key algorithms come from config, they are the same for every connection, aren't they? so if the server had only key of type RSA, and we remember it, and the server adds Ed25519 key, which has a higher priority in sshj, and we try to connect, we'll be getting that huge someone is doing something evil warning, won't we? instead of verifying using RSA while it's possible to specify key algorithms in the config, it feels like a wrong place to do it? also, i don't see how |
also, ECDSA host keys will not work, as in static PublicKey readPubKeyFromBuffer(Buffer<?> buf, String variation) throws GeneralSecurityException {
String algorithm = BASE_ALGORITHM_NAME + variation;
if (!SecurityUtils.isBouncyCastleRegistered()) {
throw new GeneralSecurityException("BouncyCastle is required to read a key of type " + algorithm);
}
... |
The negotiation algorithm is correct according to the relevant SSH RFC, but perhaps the client proposal, which you can tweak via the per-connection SshjConfig, should only consist of the subset of algorithms it already has a host key for (if not empty)? I don't even know how OpenSSH does this though. @hierynomus Do you have a recommendation on how to fix a host key type per connection?
Good catch, that seems to be an Android compatibility issue. I will look into whether I can fix it. |
OpenSSH sends all keys, but it reorders them unless you overwrite that in a config (see the penultimate paragraph):
e.g. for a single RSA key,
i'm assuming it sends all algos in order to in fact receive some host key so that it can print its hash to the user along with the warning |
I didn't know this is what OpenSSH is doing, but it should be easy to recreate in SSHJ: You can permute the host key algorithms in your instance of |
this is doable, but feels hackish. requires me to recreate config which is supposed to be global, and to have an opinion on which host key algorithms are better. i'd expect something like i'm not quite sure that you can get available host keys from |
Android Keystore private keys do not implement PrivateKey since the
raw key material is not available to applications.
With this commit, sshj's KeyType correctly detects the algorithm
associated with Android Keystore keys, which makes them usable for SSH
authentication.