Closed oberstet closed 3 years ago
I could do it. There is no real roadmap for this package. I implement things as needed. Do you want to use the package and need WAMP Cryptosign?
So Flutter/Dart is currently strong contender for mobile in this project I'm working on (not my final decision), but yes, we need WAMP and WAMP-cryptosign, and we'd would love to use connectanum-dart! I can invest time in this, help, test, etc .. but I'm a Dart dummy (and have no time to learn it quickly right now ..) .. the Dart people on the team would use it for our app code then ..
full disclosure: we want to use connectanum-dart on the client side (not router side, that'll be Crossbar.io), and want to contribute / invest time to make it fully on par feature wise with the Autobahns (rgd more obscure/advanced/not-yet-fully-official features ...)
@oberstet yes, sure. I'll start working on an implementation. You did so much for me, I basically owe you that ;)
that's cool, thanks a lot=) pls let me know should you have questions rgd wamp-cryptosign or such. because (you know that) the docs ... well;) code wise: both crossbar and all autobahns fully implement it, and we do use it in production. so it is real. and yes: we should totally have complete correct spec text for it .. yeah, and the day should have 48h;)
Yes, I know... 48 would be nice. I'll try my best to adopt:
https://github.com/crossbario/autobahn-python/blob/master/autobahn/wamp/cryptosign.py https://github.com/crossbario/autobahn-js/blob/2205e84859927cf89b7ed1bda360d52439ab9dc2/packages/autobahn/lib/auth/cryptosign.js
And this for my router:
https://github.com/crossbario/crossbar/blob/master/crossbar/router/auth/cryptosign.py
@oberstet any other suggestions?
^ those links: exactly!
more links:
Not a Dart person here, but I did the Java implementation of CryptoSign. So should probably be able to provide some testing/feedback/help as well.
@om26er, @oberstet awesome! With this help, it'll take not too long to finish it. great!
awesome, I love open source=)
one hint that might be worth mentioning: for wamp-cryptosign support, all autobahns add a dependency to libsodium https://doc.libsodium.org/ for all the underlying crypto.
that is: wamp-cryptosign is just a combination of the primitives exposed in libsodium or NaCl http://nacl.cr.yp.to/
a quick web search for "libsodium dart" turns up https://github.com/firstfloorsoftware/flutter_sodium
I have no clue about Dart ... what does look good to me though:
in autobahn on python, the lib we use there works exactly like that. well, again I don't know if that is important in Dart as well, just wanted to mention ...
This is good for a fast support. It has always been the goal to support all plattforms with this library, including web and Win/OSX/Linux. Using flutter_sodium will exclude the web support and win/mac/linux as far as I can see. That sucks a little bit. Maybe its possible to extend flutter_sodium with the missing support. I'll dive into this project after dinner...
@oberstet what do you think about this lib: https://pub.dev/packages/pinenacl Its 100% dart code and thus 100% crossplattform.
@oberstet Could you provide a test-vector like done here? Just more detailed?
Like:
// hello
privkey: asdjashaskjhf
seed: hasjhdakhjdj
pubkey: jajkshdjask
// challenge
privkey: asdjashaskjhf
seed: hasjhdakhjdj
pubkey: jajkshdjask
challenge:xxxxx
// auhtenticate
challenge_result:xxxxx
@oberstet the credentials don't change during a reconnect right? So the may be final? I somewhere read something about a token that was related to cryptosign. What is this token for or did I read it wrong?
@oberstet I started implementing it. If you could help me with the test vector:
@oberstet I also saw that you are using an activation key. is this cryptosign related or is this for xbr only? Should I also implement it?
ah, sorry, I missed this notification!! anyways, yes, here you are:
https://github.com/crossbario/autobahn-python/blob/master/autobahn/wamp/test/test_wamp_cryptosign.py
test locally:
autobahn-python$ USE_ASYNCIO=1 python -m pytest -s -v autobahn/wamp/test/test_wamp_cryptosign.py
specifically, these 2 test (we can add more of course .. eg test vectors you come up with or sth):
https://github.com/crossbario/autobahn-python/blob/df94e5f5e79e5d597d27159ea5ab0811e22ae8e8/autobahn/wamp/test/test_wamp_cryptosign.py#L74 https://github.com/crossbario/autobahn-python/blob/df94e5f5e79e5d597d27159ea5ab0811e22ae8e8/autobahn/wamp/test/test_wamp_cryptosign.py#L84
ok, above unit test code currently reads the private key used to sign the test vector challenge (32x xFF) from OPENSSH PRIVATE KEY via self.key = SigningKey.from_ssh_data(keybody)
this isn't actually that good .. because reading a key from openssh text key is yet another, special feature.
we can totally add creating a SigningKey from a bytes literal (whatever 32 bytes hardcoded in the test) using from_key_bytes
(https://github.com/crossbario/autobahn-python/blob/df94e5f5e79e5d597d27159ea5ab0811e22ae8e8/autobahn/wamp/cryptosign.py#L516)
so we need to agree on say
var privateKey = 'd511fe78e23934b3dadb52fcd022974b80bd92bccc7c5cf404e46cc0a8a2f5cd';
var challenge = 'b26c1f87c13fc1da14997f1b5a71995dff8fbe0a62fae8473c7bdbd05bfb607d'
and then check the signature resulting
Test vectors:
# test valid vectors for WAMP-cryptosign signature testing
testvectors = [
{
'priv_key': '4d57d97a68f555696620a6d849c0ce582568518d729eb753dc7c732de2804510',
'challenge': 'ff' * 32,
'signature': '9b6f41540c9b95b4b7b281c3042fa9c54cef43c842d62ea3fd6030fcb66e70b3e80d49d44c29d1635da9348d02ec93f3ed1ef227dfb59a07b580095c2b82f80f9d16ca518aa0c2b707f2b2a609edeca73bca8dd59817a633f35574ac6fd80d00'
},
{
'priv_key': 'd511fe78e23934b3dadb52fcd022974b80bd92bccc7c5cf404e46cc0a8a2f5cd',
'challenge': 'b26c1f87c13fc1da14997f1b5a71995dff8fbe0a62fae8473c7bdbd05bfb607d',
'signature': '305aaa3ac25e98f651427688b3fc43fe7d8a68a7ec1d7d61c61517c519bd4a427c3015599d83ca28b4c652333920223844ef0725eb5dc2febfd6af7677b73f01d0852a29b460fc92ec943242ac638a053bbacc200512b18b30d15083cbdc9282'
},
{
'priv_key': '6e1fde9cf9e2359a87420b65a87dc0c66136e66945196ba2475990d8a0c3a25b',
'challenge': 'b05e6b8ad4d69abf74aa3be3c0ee40ae07d66e1895b9ab09285a2f1192d562d2',
'signature': 'ee3c7644fd8070532bc1fde3d70d742267da545d8c8f03e63bda63f1ad4214f4d2c4bfdb4eb9526def42deeb7e31602a6ff99eba893e0a4ad4d45892ca75e608d2b75e24a189a7f78ca776ba36fc53f6c3e31c32f251f2c524f0a44202f2902d'
}
]
rgd activation keys:
activation keys are transported transparently in authextra
- but not used in computing the challenge or signature
activation keys are used to eg onboard new clients (accept their pubkeys and associate them with users).
the option for the app developer to provide a general authextra would be indeed very good! and of course send the authextra;)
@oberstet Thx, helped a lot. I'll finish it with the given vectors :) extending authextra
is somehow possible. since dart does not support reflections, its a bit tricky to make this work in a simple way. But I'll find a nice solution.
also, fwiw, I've added above test vectors to autobahn
also, fwiw, I've added above test vectors to autobahn
When I run the tests I get Skipped: nacl library not present
. What am I doing wrong here?
you need to install the required dependencies by doing pip install autobahn[all]
(or at least pip install autobahn[encryption]
or pip install -e .[all]
when installing from source repo).
looks like this https://gist.github.com/oberstet/2a1f559e2334dcbf5534bd7cec9fc45d
@oberstet I had to update the vectors to use no channel binding. Do you need channel binding in your upcoming project?
@konsultaner channel binding is not absolutely required: if the client does not announce it, crossbar won't use it. it'll make it slightly less secure (there is an attack scenario .. but it is very very advanced)
@oberstet ok, ill be ignoring it for now. I could not find a way to get the tls channel id from darts secure socket implementation. If you want me to implement it, just open another ticket. I will merge the branch this week. The tests were successful.
I will merge the branch this week. The tests were successful.
awesome ! \-/
thanks alot=) I'll ping a collegue, give it a try, then
for the record, above link points to code comments that clarify what tls channel binding actually provides, and why it's useful:
Application-layer user authentication protocols are vulnerable to generic credential forwarding attacks, where an authentication credential sent by a client C to a server M may then be used by M to impersonate C at another server S. To prevent such credential forwarding attacks, modern authentication protocols rely on channel bindings. For example, WAMP-cryptosign can use the tls-unique channel identifier provided by the TLS layer to strongly bind authentication credentials to the underlying channel, so that a credential received on one TLS channel cannot be forwarded on another.
@oberstet the merge to master will take some more time. I want to support putty-file and pem-file loading as well. would make it easier for people to use it on win or linux/mac
awesome ! -/ thanks alot=) I'll ping a collegue, give it a try, then
your collegue may as well just checkout the dev branch for this issue. It should work for basic tests.
I want to support putty-file and pem-file loading as well. would make it easier for people to use it on win or linux/mac
awesome! yes, support loading keys from SSH .. Putty ... OpenSSH key files. very useful.
eg one can add strong auth for WAMP and let the user simply use the key already available.
fwiw, in autobahn python, we support that via https://github.com/crossbario/autobahn-python/blob/306569985f3a4ae55e209588c7f6d873f37dfa8b/autobahn/wamp/cryptosign.py
we also support interaction with OpenBSD "signify" - a tool used widely as well.
lastly, we support talking to an SSH agent over network (loopback): this allows to have the key never leave the SSH agent, or even have the key on external HW and use SSH agent as a proxy:
https://github.com/crossbario/autobahn-python/blob/306569985f3a4ae55e209588c7f6d873f37dfa8b/autobahn/twisted/cryptosign.py#L57 https://github.com/crossbario/crossbar-examples/blob/master/authentication/cryptosign/static/client_ssh_agent.md https://github.com/crossbario/crossbar-examples/blob/master/authentication/cryptosign/static/client_ssh_agent.py
that is actually what I personally use often;) it is both super secure, and convenient. I need to unlock my key only once, as it is held in the agent. then I can just have all my WAMP client use WAMP-cryptosign, and let it talk to the SSH agent for signing during the WAMP auth handshake.
IOW: if you don't have the key unlocked, starting a WAMP Python script authenticating via WAMP-cryptosign will make Linux pop up the SSH key agent automatically!
rgd testing: ok, understood. one collegue did some basic testing (not yet cryptosign) with Connectanum and Crossbar.io - with great results=) easy to use, just works. I keep you updated ... thanks so much again already!
@oberstet The plan is to support pkcs8 and pkcs1 as well as openssh and putty. I think all key gathering mechanisms should be implemented by people using this package? Especially because flutter/dart is targeting several plattforms. Maybe there is a dart package that does all that stuff like:
IOW: if you don't have the key unlocked, starting a WAMP Python script authenticating via WAMP-cryptosign will make Linux pop up the SSH key agent automatically!
rgd signify, do you have a link to the format definition?
I think all key gathering mechanisms should be implemented by people using this package?
yes, I agree, ideally. I mean, WAMP-cryptosign uses Ed25519, and there are simply multiple "formats" or ways to create such signatures. The authentication method in WAMP doesn't care if the user computes the signature on pen & paper .. as long as the handshake doesn't timeout;)
couple of links rgd signify .. "formal definition": would be good, yes. I don't have one at hand. then it seems easy enough to deal "ad-hoc":
https://man.openbsd.org/signify.1
we're using this to sign crossbar releases:
(cpy391_4) oberstet@intel-nuci7:~/scm/s-things/thinglaunchpad$ cat ~/scm/crossbario/crossbar/crossbar/common/keys/crossbar-21-1.pub
untrusted comment: Crossbar.io 21.1 release public key
RWRCg8IXEYo6/z3ZPrKHys8UZqC4psKjy7N8ukzTN/o+vUcEyhGw2COj
this is done using
signify-openbsd -G -c 'Crossbar.io 21.1 release' \
-p crossbar-21-1.pub \
-s crossbar-21-1.sec
and the release key is logged at startup and can be printed using crossbar keys
hooray! awesome=) so the upcoming 1.0.14 will have it released I guess:
### 1.0.14
- support wamp cryptosign
- support several key loading mechanism
Exactly 😁 I just need to add somemore test to keep the coverage up high. Especially the openssh. Ill keep working on the different private key formats. I may also putt that code into an extra package...
@oberstet I added decoding openssh keys with password protection. Just to keep you updated.
@oberstet Digging into this whole private key encryption topic led me into this hint from wikipedia
I think it would be nice to have a WAMP-Cryptobox format that uses an ASN.1 Structure, or maybe just a copy of PKCS #8 but uses Argon2 instead of PBKDF2. Just like we have it in SCRAM? What do you think about it?
-----BEGIN WAMP PRIVATE KEY-----
...
-----END WAMP PRIVATE KEY-----
I added decoding openssh keys with password protection.
oh, that's cool!
I mean, all these methods make sense depending on situation:
now, I actually don't know what KDFs are supported by OpenSSH for Ed25519 private keys (the "KDF == whatever" ..).
supporting a KDF that isn't supported by OpenSSH: not so sure .. at least I would try to coordinate or at least reach out to the OpenSSH developers in this case.
quick web search turns up these links .. still not sure about ^:
does openssh use bcrypt by default, and pbkdf2 only via command line option? it does not seem that argon2 would be supported?
I mean: yes, Argon2 seems strictly better than bcrypt or pbkdf2, so having the option would be nice .. but without support in openssh itself as well?
Sidenote: "WAMP-Cryptobox" -- guess a typo? just in case: the authentication method ^ is WAMP-Cryptosign. The WAMP-Cryptobox method is for end-to-end application data encryption .. yet another thing we have in AB/CB, but different from the former https://github.com/crossbario/crossbar-examples/tree/master/encryption/cryptobox - finally, XBR is building on that and going even further: e2e app payload encryption with keys exchanged by a key exchange ("market maker") that can do the key exchange as part of a "key buy/sell transaction" on an off-chain payment channel anchored in on-chain smart contracts. This really is too much to introduce "casually" .. just wanted to note because there is a connection between WAMP-Cryptobox and XBR and "WAMP-Cryptobox" is different from "WAMP-Cryptosign" ...
supporting a KDF that isn't supported by OpenSSH
as mentioned: if openssh itself supports Argon2, I'd be definitely +1 if not, then "maybe" .. and the kinda meta argument is:
in a way being compatible with the supported key format of openssh allows me to use this external tool (openssh) for key generation, key export, whatever .. a 2nd tool (besides the WAMP client library) ... this is good! trust, security, interop. and we would loose that if we invented an extension to the openssh key format for Argon2 which isn't supported by openssh
turned around: if we only needed any key format for WAMP-cryptosign itself without regards to compatibility with openssh, then we are of course completely free to do whatever we like. Which could be a goal in itself of course .. because a private key format specified in WAMP would at least provide cross-WAMP-implementation compatibility. I would say: if we can technically use OpenSSH key format for everything we want from WAMP perspective, we should totally reuse that and not reinvent the wheel ...
guess a typo
True I keep mixing it up.
supporting a KDF that isn't supported by OpenSSH
@oberstet Your right... this doesn't really make 100% sense. I just thought of a way to make it more safe. I think I remembered that autobahn-js stored the private key into the local storage. So I thought it would be nice if you could read the existing formats (what i am working on atm) but export/store them in a more secure way. Or even if you want to share the key between multiple machines. The most secure password encrypted way seemed not to exist these days. Thats why I came up with using PKCS8 with argon2d.
I had a quick look: as far as I see, the openssh key format
https://coolaj86.com/articles/the-openssh-private-key-format/
could in principle store eg "argon2id" as kdf name, but openssh itself only supports "bcrypt":
we could ask / and or just extend and move ahead ... however, then we need keygen as well.
in autobahn, we'd need to add bits to
well, also fix;)
if kdf != b'none':
raise Exception('passphrase encrypted private keys not supported')
@oberstet I sent a FR to openssh. Lets see what they say.
@konsultaner Hi Richard, wanted to take the chance to introduce you to my collegues James https://github.com/jyzhang (PST timezone) and Sergey https://github.com/timeout2x (CET timezone) who will work on the Dart/Flutter side of the project/product I'm also part of. One thing I'm unsure: 1.0.14 is not yet released, right? which would explain that there isn't a tagged version yet;) np, so currently they should use master to get started (we need wamp-cryptosign dart->crossbar .. so we get some real-world testing for connectanum-dart)? also, do you have some simple example client (Dart) using wamp-cryptosign? sorry, at this point, I'll probably not be of much use since I have basically zero Dart know how;) also a reason I wanted to get you guys in direct touch. and of course to give feedback (it will be used now;)
One thing I'm unsure: 1.0.14 is not yet released, right?
No I wanted to at least have all tests written for the current code until I release. I'll try to make that happen until the end of next week. We'll see.
we need wamp-cryptosign dart->crossbar .. so we get some real-world testing for connectanum-dart
Actually there is someone that uses this lib with crossbar already. He added the other issues and it seems to work. I haven't used it in production yet, but have a project that works with connectanum. If you want to use raw sockets, be aware that I extended the protocol a little bit to support message lengths > 16MB (or what ever was the highest).
do you have some simple example client (Dart) using wamp-cryptosign
final client1 = Client(
// The realm to connect to
realm: 'demo.connectanum.receive',
// Add the authmethods
authenticationMethods: [
CryptosignAuthentication.fromHex('ffaa2233fff22334433231412515')
],
// We choose WebSocket transport
transport: WebSocketTransport(
'wss://www.connectanum.com/wamp',
// if you want to use msgpack instead of JSON just import the serializer
// from package:connectanum/msgpack.dart and use WebSocketSerialization.SERIALIZATION_MSGPACK
Serializer(),
WebSocketSerialization.SERIALIZATION_JSON,
));
Session session1;
try {
// connect to the router and start the wamp layer
session1 = await client1.connect(
options: ClientConnectOptions(
reconnectCount: 10, // Default is 3
reconnectTime: Duration(milliseconds: 200) // default is null, so immediately
// you may add ping pong options here as well
)
).first;
// if you want to change the options after each reconnect, use this event
client1.onNextTryToReconnect.listen((passedOptions) {
// enlarge the time to wait after each reconnect by 500ms
passedOptions.reconnectTime = Duration(
milliseconds: passedOptions.reconnectTime.inMilliseconds + 500
);
});
@timeout2x @jyzhang If you have any question, you may also just skype call me or send me an email. @oberstet should have my details. I you find issues, please post them on github.
thanks for the example! much appreciated.
Actually there is someone that uses this lib with crossbar already. He added the other issues and it seems to work.
cool! that sounds great.
If you want to use raw sockets, be aware that I extended the protocol a little bit to support message lengths > 16MB (or what ever was the highest).
I think that should be fine ...
Ok, I would love to try it myself.
As said, I don't know Dart, but it seems easy enough to read and copy-pasta stuff together. Code wise. Btw, the API of connectanum seems nice and straightforward .. I can deal with that! kudos.
Anyways, this is what I have: https://github.com/oberstet/scratchbox/tree/master/flutter/ex1
Now I'm stuck on:
oberstet@intel-nuci7:~/scm/oberstet/scratchbox/flutter/ex1$ flutter pub get
Running "flutter pub get" in ex1... 2.274ms
oberstet@intel-nuci7:~/scm/oberstet/scratchbox/flutter/ex1$ dart test_client.dart
test_client.dart:12:13: Error: Getter not found: 'CryptosignAuthentication'.
CryptosignAuthentication.fromHex('ffaa2233fff22334433231412515')
^^^^^^^^^^^^^^^^^^^^^^^^
Likely I am missing a trivial change or what .. not sure .. I do have a dependency reference to the master branch .. I think .. https://github.com/oberstet/scratchbox/blob/484b5243f7639ba4d2e9d42154961d535ec2abfe/flutter/ex1/pubspec.yaml#L10
Could you help me out? Sorry for newbie questions ..
As I see it flutter pub get
only gets released versions of packages on pub.dev . I'll try to get it done today.
rgd my example from above. My connectanum demo does not support cryptosign yet. You may have to exchange the router url.
Btw, the API of connectanum seems nice and straightforward
Thanks :)
@oberstet I released version 1.1.0
thanks! unfortunately, sth is still wrong:
My connectanum demo does not support cryptosign yet. You may have to exchange the router url.
ok, got it. I'll swap the URL etc once I have it starting at all in the first place ...
aahh .. ok, not sure if that is right, but when adding:
import 'package:connectanum/src/authentication/cryptosign_authentication.dart';
and changing URL and key, I am making progress:
Are there plans to support WAMP Cryptosign as authentication method (for clients)?