MaidSafe Dev Update :safe: 15th March 2016

Might be similar to downloading software or programs, where there’s a link to each new version with different “fixes” etc., but each file is immutable and therefore safe because you know nobody else has tampered with it.

This is part of the conversation and security. If companies are compelled to backdoor a module, we don’t want it. If though and upgrade happens we want then we will need to specifically change the hash. So you are correct. If we use the service route then it is automatic though. So there is things to discuss. Either way though the data stays forver, so hacked or backdoored code can be ignored and we can stick to code that does work if we wish. Same ith documents/contracts etc. They stay forever. So we do have the ability to auto-upgrade and with care set versions we wish to roll back to if we wish. Then these versions can be forked to update if we are not happy with what they have done etc.

I think we can get the best of both worlds.


My JavaScript is rather rusty, but it looks like CORS isn’t enabled from my scruffy testing.

I can make a call to auth and the launcher asks me to confirm access, but if I use the token to subsequently try to POST to nfs/file, I get ‘Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response’.

Note that the examples in the API documentation seem to be rather buggy. It could be related to me using browserify (for the first time!) on the node.js examples, but it looks like response.body.token is correct, rather than response.token, etc.

Still, it was nice to see the launcher pop-up and ask me to authenticate my app. Tbh, it feels good just to get a chance to play around with it! :slight_smile:


Thank you for the response.
I think I understand most of it.

Also a hash is not readable: best to be accompanied with describing comment in source code or so.
If hash is chosen as reference method for a module, then it is best to have a minimum of references (all to be manually updated at upgrade) in 1 website to that module (preferably only 1).

I’m not that familiar with web development, but I presume that this is the responsibility of the webpage developer and that there are already good enough methods in html etc. to accomplish this?


No, no, no. It’s embrace, extend, and then extinguish. The order is extremely important.

1 Like

If there is problem with CORS I can address it quick. Will check this out. Also, I find that I missed to document on how to invoke from web browsers using the api.safenet instead of localhost:8100. I will make a quick sample and check this out.

That’s corrected in the document. Thanks :slight_smile:


Oh, very good! I was thinking before sleeping about whether there should be an alias URL which can just hit port 80 and achieve the same.

So, access isn’t be restricted by design (for security) at this phase?

Edit: BTW, the code I was working with was literally hacked together late last night from the examples, so there is a good chance the problem is my end! The message back looked like there was some security issue though.

No problem! :slight_smile:

BTW, the naming of the token variable changes between some examples too, which may throw some people.

It would be good to have a wee demo web app too somewhere, where all the source code was present and you could do the basics (authenticate, put a file, read a file, reuse existing session, etc). These sort of live examples are great for pulling apart and customising.


Thank You for all the effort!

So every Client/Vault will run it’s own STUN-Server? Is this a specialized version for P2P and anonymity?

More info on STUN for those interested. Link 1 and Link 2.

1 Like

Yes it is STUN like capabilities but not the STUN rfc we have implemented. More like echo servers (here is your external address and many of us can see it etc.) using a protocolMapper type (our type).

CRUST at the moment is not using authenticated encryption for serialisation. IT will though via the mio version which ensures no route poison attacks etc.


I’ve been reading through some of the API documentation and am finding it a bit hard to understand. A bit too much tech language and not enough defining of terms and examples/tutorials I think. I know it JUST came out and that’s awesome but some expounding would be good.

1 Like

Nice, looking great :smiley:

Trying to build against the launcher, I can already make connection with the launcher through the nodejs sample code and allow safe drive access, however it gives back this:

nodejs fetch.js

aughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));Mod
Error: auth() received invalid user or password
at Request.auth (/usr/lib/nodejs/request/index.js:1067:11)
at Request.init (/usr/lib/nodejs/request/index.js:310:10)
at new Request (/usr/lib/nodejs/request/index.js:124:8)
at Function.request [as get] (/usr/lib/nodejs/request/index.js:1279:11)
at Request.onAuthResponse [as _callback] (/home/test/safenetwork/fetch.js:98:15)
at Request.self.callback (/usr/lib/nodejs/request/index.js:148:22)
at Request.EventEmitter.emit (events.js:98:17)
at Request. (/usr/lib/nodejs/request/index.js:896:14)
at Request.EventEmitter.emit (events.js:117:20)
at IncomingMessage. (/usr/lib/nodejs/request/index.js:847:12)

I basically embedded the file fetch nodejs sample code within the auth post sample code callback. Not sure if I understand correctly but I would assume it should give the right user and password when authorized by the launcher?

Code listed below:

`// libsodium wrappers is used for crypto
var libsodium = require(‘libsodium-wrappers’);
var httpRequest = require(‘request’);

// Generate Assymetric Key pairs
var assymetricKeys = libsodium.crypto_box_keypair();
// Generate random Nonce
var nonce = libsodium.randombytes_buf(libsodium.crypto_box_NONCEBYTES);;

// Creating the authorisation request payload
var payload = {
app: {
name: ‘Demo App’,
version: ‘0.0.1’,
vendor: ‘maidsafe’,
id: ‘org.maidsafe.demo’
// Converting assymetric public key to base64 string
publicKey: new Buffer(assymetricKeys.publicKey).toString(‘base64’),
// Converting nonce to base64 string
nonce: new Buffer(nonce).toString(‘base64’),
// List of permissions requested
permissions: [‘SAFE_DRIVE_ACCESS’]

// Preparing the request object
var request = {
url: ‘http://localhost:8100/auth’,
headers: {
‘Content-Type’: ‘application/json’
json: payload

// Handle the response recieved from the launcher
var onAuthResponse = function(err, response) {
if (err) {
throw err;
if (response.statusCode !== 200) {
throw new Error('Failed with error code: ’ + response.statusCode);
// The encrypted symmetric key recieved as base64 string is converted to Uint8Array
var cipherText = new Uint8Array(new Buffer(response.body.encryptedKey, ‘base64’));
// The asymmetric public key of launcher recieved as base64 string is converted to Uint8Array
var publicKey = new Uint8Array(new Buffer(response.body.publicKey, ‘base64’));
// the cipher message is decrypted using the assymetric private key of application and the public key of launcher
var data = libsodium.crypto_box_open_easy(cipherText, nonce, publicKey, assymetricKeys.privateKey);
// The first segment of the data will have the symmetric key
var symetricKey = data.slice(0, libsodium.crypto_secretbox_KEYBYTES);
// The second segment of the data will have the nonce to be used
var symetricNonce = data.slice(libsodium.crypto_secretbox_KEYBYTES);
// Authorisation token
var token = response.body.token;
// List of persmissions approved by the user
var permissions = response.body.permissions;
// Creating the payload
var filePath = ‘/private/snapshot_blob.bin’;
var isPathShared = false;

// Change if the query parameters are to be sent
var appendQueryParams = false;

// Preparing the request options with the auth token
var request = {
url: ‘http://localhost:8100/nfs/file/’ + encodeURIComponent(filePath) + ‘/’ + isPathShared,
auth: {
bearer: token

// send query parameters
// The query parameters are encrypted
if (appendQueryParams) {
var queryParams = ‘offset=0’;
request.url += ‘?’;
var encryptedParams = libsodium.crypto_secretbox_easy(queryParams, symmetricNonce, symmetricKey).toString(‘base64’);
request.url += encryptedParams;

// Handling the response
var onResponse = function(err, res, body) {
if (err) {
return console.log(‘Err:’, err);
if (res.statusCode === 400) {
return console.log(‘Bad request’);
if (res.statusCode === 401) {
return console.log(‘Unauthorised’);
body = new Buffer(body, ‘base64’);
// Decrypt the file content
var decryptedData = libsodium.crypto_secretbox_open_easy(new Uint8Array(body), symmetricNonce, symmetricKey);
console.log(‘File Content:’, new Buffer(decryptedData).toString());
// Send get file request
httpRequest.get(request, onResponse);

// Sending authorisation request, onAuthResponse);


1 Like

I just ran the same code of yours and it works fine. I get an error response
{"errorCode":-1502,"description":"FfiError::PathNotFound"} because I don’t have the file. There was a typo in the variable naming though, corrected and pasted as a gist

But the typo has nothing to do with the error reported. I tested it on Windows. If you still have an issue, please pass on more info on the platform and the version of nodejs. We have developed and tested on 5.0 and above.


Thanks, works with the latest nodejs version upgrade!


Facebook, Twitter, Reddit, Instagram, Tumblr, Imgur, etc., etc.

1 Like

The potential for SAFE to be a Silicon Valley unicorn slayer is crazy…am I right!?:stuck_out_tongue_closed_eyes:

If it was me, I’d me nervous as hell right now if I was these guys…they are gonna wake up one day and be all like “Where did our metadata go?..SAFE what???..”


Krishna, did you get chance to look at this? I am thinking of having another play tonight!

1 Like

He should be asleep (India) but he works huge hours, I would say safe to play tonight and he will be around in about 7 hours or so, but ye never know :smiley:


Thanks, David. I ran my scripts as node.js and after some debugging, I managed to update a file and retrieve it again, which was pretty cool! However, browserify still resulted in CORS issues (with/without api.safenet as the URL), so it looks like the Access-Control-Allow-Headers will need setting to allow this.


I so hope this is opt-in. I wish the web proxy was too (granted it doesn’t do anything if you haven’t setup the PAC file)