ghbutton / react-native-simple-crypto

A simpler React-Native crypto library
https://www.npmjs.com/package/react-native-simple-crypto
MIT License
42 stars 25 forks source link

Common Crypto AES module fails to decrypt cipherText from WebCrypto API [iOS / Objective C] #1

Closed pedrouid closed 5 years ago

pedrouid commented 5 years ago

Currently the AES module in react-native-simple-crypto has two methods to encrypt and decrypt using the AES-128-CBC algorithm. It correctly encrypts and decrypts cipherTexts encrypted by itself. However when passed a cipherText encrypted using the WebCrypto API with the same algorithm, the cipher fails to decrypt it.

Example

import RNSimpleCrypto from "react-native-simple-crypto";

// from browser we have the cipherText, key and iv in hexadecimal encoding
const cipherTextHex = "58c23c4b7a4083e1032bed9924be9e6df07714bba0f7ac3f75c7af2cc948925f6852ce378bda2a5a5104eb14b7c38bf6533635e179230fc3badbca7b4d85d757a19f10974ceafdfbbc67b1faba9d7d38a396685852391aef687ddb7aadb2c4927461130ffc4c8e161205b239df9c42e03c6f904698c05af368e6d69888b0a9ed9b14ed2263a760f0dcd70e4da7f0d89f02484c16a1070e7a0e908246fef66823"
const keyHex = "8606388f144bfa3b318cbc7eb0a1267ed6ddea6b5fc21a66bb982c2d345b7d28"
const ivHex = "2e1388a7af1026e61c573d66839b31cb"

// convert hexadecimal encoding into array buffers
const cipherText = RNSimpleCrypto.utils.convertHexToArrayBuffer(cipherTextHex);
const key = RNSimpleCrypto.utils.convertHexToArrayBuffer(keyHex);
const iv = RNSimpleCrypto.utils.convertHexToArrayBuffer(ivHex);

// use decrypt method from our library
const result = await RNSimpleCrypto.AES.decrypt(cipherText, key, iv);

Expected Result

// result
{
  id: 1547162850087708,
  jsonrpc: "2.0",
  method: "wc_sessionRequest",
  params: [
    { peerId: "67b121c8-d66c-44d0-9d0f-6fb5e9235e0c", peerMeta: null }
  ]
};

Actual Result

// error
Error: Decrypt failed
    at createErrorFromErrorData (NativeModules.js:121)
    at NativeModules.js:78
    at MessageQueue.__invokeCallback (MessageQueue.js:398)
    at MessageQueue.js:137
    at MessageQueue.__guardSafe (MessageQueue.js:314)
    at MessageQueue.invokeCallbackAndReturnFlushedQueue (MessageQueue.js:136)
    at debuggerWorker.js:70

The only occurence for this error message is Line 26 on file RCTAes.m https://github.com/WalletConnect/react-native-simple-crypto/blob/master/ios/RCTCrypto/RCTAes.m#L26 Which is returned by checking the result is nil from the cipher on file Aes.m https://github.com/WalletConnect/react-native-simple-crypto/blob/master/ios/RCTCrypto/lib/Aes.m

Additionally if we encrypt the same expected result with the same key and iv using the library, we get a different cipherText

8dd33279c17afad8563bbc1fc60c6b306121ffb19ffb264f8b12a3292dbe6ca2faae0c2106fded72545b2c4509daad9e9b7b2e54ef3eb03f5562daf088bbcee642417a2c0305e708679403f91298f32f3e665406dfd3a689f126d03c01c66f518993626770023379c8726a0825570db508987156e125adc3f8af137eb87ef4732f4536ba84cffe7e9d9a04a334a129b499f387bfcca03bcf5092872991db969f

I've checked the WebCrypto API and according to the spec it should follow the same algorithm AES-128-CBC with PKCS7 padding https://www.w3.org/TR/WebCryptoAPI/#aes-cbc-description

gitcoinbot commented 5 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


This issue now has a funding of 100.0 DAI (100.0 USD @ $1.0/DAI) attached to it as part of the WalletConnect fund.

gitcoinbot commented 5 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


Work has been started.

These users each claimed they can complete the work by 1 month, 3 weeks ago. Please review their action plans below:

1) iamonuwa has started work.

Skipped this task because I was thinking it was Objective C, On a closer look discovered its react native. Am available to work on this task. Will be ready before end of weekend.

Learn more on the Gitcoin Issue Details page.

2) bb2000 has started work.

Pull request already submitted to fix issue. I will also make any changes needed to make the solution acceptable.

Learn more on the Gitcoin Issue Details page.

pedrouid commented 5 years ago

Here is the WebCrypto API method for encrypting

async function aesCbcEncrypt (data, key, iv) {
  const AES_ALGORITHM = 'AES-CBC'
  const AES_LENGTH = 128
  const cryptoKey = await window.crypto.subtle.importKey(
    'raw',
    key,
    { length: AES_LENGTH, name: AES_ALGORITHM },
    true,
    ['encrypt', 'decrypt']
  )
  const result = await window.crypto.subtle.encrypt(
    {
      iv,
      name: AES_ALGORITHM
    },
    cryptoKey,
    data
  )
  return result
}
gitcoinbot commented 5 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


Work for 100.0 DAI (100.0 USD @ $1.0/DAI) has been submitted by:

  1. @bb2000

@pedrouid please take a look at the submitted work:


gitcoinbot commented 5 years ago
Bug Squasher ⚡️ A *Bug Squasher* Kudos has been sent to @bb2000 for this issue from @pedrouid. ⚡️ Nice work @bb2000! Your Kudos has automatically been sent in the ETH address we have on file.
gitcoinbot commented 5 years ago

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


The funding of 100.0 DAI (100.0 USD @ $1.0/DAI) attached to this issue has been approved & issued to @bb2000.