stacks-archive / radiks

A client-side framework for building model-driven decentralized applications.
MIT License
96 stars 33 forks source link

Radiks : problem with encryption while saving models #97

Open bricemacias opened 4 years ago

bricemacias commented 4 years ago

Hi, I just started using radiks and my own radiks-server on my Dapp.

I know my radiks-server is working because I can fetch radiks User or Model with fetchList(), even if I get an empty array because nothing is saved yet. If I change the apiServer in radiks configure, the fetchList() method fails. That way, when I put back the correct apiServer url in configure and I get empty array, at least I know my radiks server is up and running.

The problem is when I try to save anything with the save() method.

If I use the example given in the documentation with the simple Todo Model :

class Todo extends Model {
  static className = 'Todo';
  static schema = {
// all fields are encrypted by default
title: String,
completed: Boolean,
  };
}

If I create a new Todo model, and then try to use save(), I get the following error :

index.js:311 
Uncaught (in promise) TypeError: First argument must be a string, Buffer, ArrayBuffer, 
     Array, or array-like object.
        at fromObject (index.js:311)
        at from (index.js:137)
        at Function.push.../node_modules/buffer/index.js.Buffer.from (index.js:149)
        at Object.getPublicKeyFromPrivate (keys.ts:43)
        at signECDSA (ec.ts:377)
        at Todo.sign (model.ts:211)
        at model.ts:131 

Same, if y create a user with the method User.currentUser() , and then try to save it, I get the following error :

fetchUtil.ts:12 
   POST https://hub.blockstack.org/store/{adressId}/BlockstackUser/{myBlockstackUserId}
   with server error 500

and

 utils.ts:401 
 Uncaught (in promise) Error: Error when uploading to Gaia hub.
         at Object.<anonymous> (utils.ts:401)
         at Generator.next (<anonymous>)
         at fulfilled (tslib.es6.js:71)

Finally, if this time I try to create User with the method User.createWithCurrentUser() method, I get the following error :

 aesCipher.ts:90 
 Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is 
   not of type '(ArrayBuffer or ArrayBufferView)'
      at WebCryptoAesCipher.<anonymous> (aesCipher.ts:90)
      at Generator.next (<anonymous>)
      at fulfilled (tslib.es6.js:71)

With another 500 error after that, saying

“Error When Uploading to Gaia Hub”.

💡NB : If I try the normal getFile() and putFile() methods without using radiks, that works perfectly though

After some tries, I managed to save a Todo, but apparently it’s an encryption problem. When I get the list of Todos I created, inside of the attributes of the object I get a blockstack error saying :

“Unable to get public key from cipher object. You might be trying to decrypt an unencrypted object.”

and when I create a Todo, I get the following error :

Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
    at WebCryptoAesCipher.<anonymous> (aesCipher.ts:90)
    at Generator.next (<anonymous>)
    at fulfilled (tslib.es6.js:71)

And if I create a Todo, but this time whitout encryption, everything works perfectly.

I really don't know if this is related to me or to radiks itself...

friedger commented 4 years ago

@bricemacias, how do you authenticate? When are you calling User.createWithCurrentUser?

Which documentation didyou follow? (so that it could be improved..)

bricemacias commented 4 years ago

@friedger, I followed the following documentations :

I also looked into the code of different examples on github like banter, lettermesh, debut social network, and goodtimes

I used User.createWithCurrentUser inside my login function like so :


  if (userSession.isSignInPending()) {
    const asyncPendingLogin = async () => {
      await userSession.handlePendingSignIn();
      const user = await User.createWithCurrentUser();
      await user.save();
      // console.log('new user', user);
      window.location.href = window.location.origin;
      setLoading(false);
    };
    asyncPendingLogin();
  }

I'm using hooks and functional components, so this replaces the usual ComponentWillMount usual example. I know my login is working because when I take off the radiks part, meaning those two lines :

    const user = await User.createWithCurrentUser();
     await user.save();

everything works perfectly.

I also tried the User.currentUser method once my loggin is successful like so :

const App = ({ appConfig, userSession, handleSignOut }: AppProps) => {
  const [user, setUser] = useState({});
  const notification = useGlobalMessage(); // not important here
  const [, dispatch] = useStore(); // not important here 

  useEffect(() => {
    const asyncLoggedIn = async () => {
      const user = User.currentUser();
      await user.save();
      setUser(user);
      console.log('existing user', user);
    };
    asyncLoggedIn();
  }, [userSession]);

[...]

And this time, the user is created, and I can console.log it, but when I try to save it, it also puts an error like described on my previous comment :

fetchUtil.ts:12 
   POST https://hub.blockstack.org/store/{adressId}/BlockstackUser/{myBlockstackUserId}
   with server error 500

and

 utils.ts:401 
 Uncaught (in promise) Error: Error when uploading to Gaia hub.
         at Object.<anonymous> (utils.ts:401)
         at Generator.next (<anonymous>)
         at fulfilled (tslib.es6.js:71)

I looked into radiks source code, isn't it this related to the fact that I'm not creating groups before trying to save the user ? Because I have the impression that radiks uses a group signing key to encrypt data, and not a single User signing key, which would explain why saving data without encryption using radiks works, but if that's the case, it's nowhere around in any documentation...

hstove commented 4 years ago

@bricemacias , you don't need to make a UserGroup in order to save models.

Would you be able to share a code sample that reproduces the problem? What's odd is you're getting 500 errors when uploading the file to Gaia. There must be something funky going on with the payload that is being sent to Gaia. I've actually never seen this error you're seeing:

Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'

Can you share a code snippet of the SubtleCrypto model? I think that's where the problem is coming from.

ZiNai commented 4 years ago

if (userSession.isSignInPending()) { const asyncPendingLogin = async () => { await userSession.handlePendingSignIn(); const user = await User.createWithCurrentUser(); await user.save(); // console.log('new user', user); window.location.href = window.location.origin; setLoading(false); }; asyncPendingLogin(); }

I tried your code ,but the bug still works ಥ_ಥ

this is my chrome console log

[DEBUG] connectToGaiaHub: https://hub.blockstack.org/hub_info
aesCipher.js:69 Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
    at WebCryptoAesCipher.<anonymous> (aesCipher.js:69)
    at Generator.next (<anonymous>)
    at fulfilled (tslib.es6.js:86)
logger.js:41 [DEBUG] uploadToGaiaHub: uploading SigningKey/6b0707978cc2-49d6-a034-9bc6c3ffd12a to https://hub.blockstack.org
logger.js:41 [DEBUG] uploadToGaiaHub: uploading BlockstackUser/zinai_bs.id.blockstack to https://hub.blockstack.org
aesCipher.js:69 Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
    at WebCryptoAesCipher.<anonymous> (aesCipher.js:69)
    at Generator.next (<anonymous>)
    at fulfilled (tslib.es6.js:86)
hub.blockstack.org/store/1PBvFRr5y5Cj7MfZrHRbjJ2WnUA8jsSGXC/BlockstackUser/zinai_bs.id.blockstack:1 Failed to load resource: the server responded with a status of 500 ()
utils.js:422 Uncaught (in promise) Error: Error when uploading to Gaia hub.
    at Object.<anonymous> (utils.js:422)
    at Generator.next (<anonymous>)
    at fulfilled (tslib.es6.js:86)

this is my radiks-server error logs

0|index    | (node:6127) DeprecationWarning: collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.
0|index    | Error: Error when validating: No signing key is present with id: '56e1b63f54e4-4f8e-b849-820196aea8f1'
0|index    |     at errorMessage (/home/ubuntu/start/node_modules/radiks-server/app/lib/validator.js:19:9)
0|index    |     at Validator.validateSignature (/home/ubuntu/start/node_modules/radiks-server/app/lib/validator.js:94:11)
0|index    |     at process._tickCallback (internal/process/next_tick.js:68:7)
0|index    | (node:9940) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
0|index    | (node:9940) DeprecationWarning: collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.
0|index    | Error: Error when validating: No signing key is present with id: 'c4369e08eb19-4fc4-9f4e-26fb9994659f'
0|index    |     at errorMessage (/home/ubuntu/start/node_modules/radiks-server/app/lib/validator.js:19:9)
0|index    |     at Validator.validateSignature (/home/ubuntu/start/node_modules/radiks-server/app/lib/validator.js:94:11)
0|index    |     at process._tickCallback (internal/process/next_tick.js:68:7)
0|index    | (node:10174) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
0|index    | (node:10174) DeprecationWarning: collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.
0|index    | (node:10796) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
0|index    | (node:10796) DeprecationWarning: collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.

This login process is very confusing,espasically the code :

await User.createWithCurrentUser()

That` means I will create a new user to my radiks-server. But when is the usersession inject the User Obj, can support more clearly code like this:

// After did the SignIn operation 
const sessionNow = getUserSessionNow()
// if login get the User Obj By session or others
const currentUser = getUserBySessionNow( sessionNow )
// return the status clearly
const [pending,error,success ] = await currentUser.create()
}

Sorry for saying so much, thank you very much for your cool work!👍

scholl commented 4 years ago

Hello,

I have the same issue with the function User.createWithCurrentUser() don't work currectly.

Error Log:

errors.ts:48 Uncaught (in promise) Error at ec.ts:322 at Generator.next () at tslib.es6.js:73 at new Promise () at Module.__awaiter (tslib.es6.js:69) at decryptECIES (ec.ts:315) at helpers.ts:46 at Array.forEach () at decryptObject (helpers.ts:36) at async BlockstackUser.decrypt (model.ts:189) at async BlockstackUser.fetch (model.ts:182)

Uncaught (in promise) Error at ec.ts:322 at Generator.next () at tslib.es6.js:73 at new Promise () at Module.__awaiter (tslib.es6.js:69) at decryptECIES (ec.ts:315) at helpers.ts:46 at Array.forEach () at decryptObject (helpers.ts:36) at async SigningKey.decrypt (model.ts:189) at async SigningKey.fetch (model.ts:182)

Uncaught (in promise) TypeError: Failed to execute 'encrypt' on 'SubtleCrypto': The provided value is not of type '(ArrayBuffer or ArrayBufferView)' at WebCryptoAesCipher. (aesCipher.ts:90) at Generator.next () at fulfilled (tslib.es6.js:70)

scholl commented 4 years ago

Hello, everyone, i did some more tests and therefore i switched to the blockstack API version 19.3.0 (before 21.0.0) with this version all mentioned errors disappear and the communication with Gaia and Radiks seems to work.