Skip to content
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

loading indutny/elliptic library to browser on demand #956

Merged
merged 34 commits into from
Oct 25, 2019

Conversation

chesnokovilya
Copy link
Contributor

No description provided.

@chesnokovilya chesnokovilya changed the title WIP: loading indutny/elliptic library to the browser on demand WIP: loading indutny/elliptic library to browser on demand Aug 30, 2019
@chesnokovilya chesnokovilya force-pushed the web-loading-testing branch 5 times, most recently from 987ef8e to e2ddb07 Compare September 6, 2019 07:25
@chesnokovilya chesnokovilya changed the title WIP: loading indutny/elliptic library to browser on demand loading indutny/elliptic library to browser on demand Sep 6, 2019
src/build.env.js Outdated Show resolved Hide resolved
src/openpgp.js Outdated Show resolved Hide resolved
src/util.js Outdated Show resolved Hide resolved
test/crypto/elliptic.js Outdated Show resolved Hide resolved
src/openpgp.js Outdated Show resolved Hide resolved
src/util.js Outdated Show resolved Hide resolved
src/build.env.js Outdated
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

export default {
use_indutny_elliptic: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this should be set at runtime instead of compile time, but maybe you don't even need a config option for this. People could just do something like

openpgp.loadElliptic = () => {
  throw new Error('Elliptic is not included');
};

Then, you can also remove all the getUseElliptic checks, as it will automatically throw a useful error when it's trying to load elliptic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This option prevents openpgp from tryng to load elliptic. I think this is useful. For example browserify has exclude and external options. At runtime we could check if elliptic should be loaded but not loaded.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example code I posted would also prevent OpenPGP.js from trying to load elliptic, right? It is a bit more work than passing a flag, but the advantage is that you don't have to create a special build of OpenPGP.js, and that it simplifies OpenPGP.js because we can always just call loadElliptic before checking first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to substitute function content using grunt replace command? It is not clear for me =).

src/openpgp.js Outdated Show resolved Hide resolved
this.getIndutnyCurve = util.getUseElliptic() ? async name => {
const elliptic = getElliptic() || await loadElliptic(build.external_indutny_elliptic_path);
return new elliptic.ec(name);
} : undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also put this function in indutnyKey.js - it doesn't use this, so it doesn't have to be a method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IndutnyKey.js is not public now, I could make it public and move this function here.

src/crypto/public_key/elliptic/indutnyKey.js Show resolved Hide resolved
Comment on lines 210 to 212
indutny_elliptic_fetch_options: {
credentials: 'include'
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This default credentials: 'include' is not necessary, it can be set by the application if needed. You can just default to {} for the options, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

package.json Outdated
"tweetnacl": "github:openpgpjs/tweetnacl-js#1ef755f2b252a3e328ac739848d00e0dad76be2d",
"web-stream-tools": "github:openpgpjs/web-stream-tools#dc4b05e8a272b45819233f3df735423432beacfc",
"email-addresses": "github:openpgpjs/email-addresses#686743c6452b44bafcd06d47db7f36ddf3f3f118"
"whatwg-fetch": "^2.0.3"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty nitpicky, but could you keep these packages in the order they were in? I know they're usually in alphabetic order, but the order they were in was to roughly separate what was needed only for development (everything up to sinon) and what packages end up in a build (everything starting from text-encoding-utf-8).
Also, even if you disagree with that, keeping them in the same order in this PR would make it easier to see what changed here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Npm kinda do it by itself, once I run npm install elliptic. May be we could switch to the new ordering convention? It is bothersome to rearrange lines manually after each change, or switching to another git branch.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be we could switch to the new ordering convention?

Yeah, we could do that, but preferably not in this PR, since it makes it harder to see what changed.
Once we switch to ES6 modules, we'll move the devDependencies starting from text-encoding-utf-8 to dependencies, so then is probably a good time to fix the ordering.

src/lightweight_helper.js Outdated Show resolved Hide resolved
src/lightweight_helper.js Outdated Show resolved Hide resolved
script.integrity = integrity;
}
script.onload = e => resolve(e);
script.onerror = e => reject(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
script.onerror = e => reject(e);
script.onerror = () => reject(new Error('Failed to load ' + path));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have researched a bit errors that are thrown here, they are network related. This promise would be resolved even if path is wrong, and actually elliptic has failed to load.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. But e is not an error object, it is an event object. You should throw an error instead of an event. Even for network errors, "failed to load" is pretty descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is actually error event is passed here, I would better catch it in loadEllipticPromise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is an error event, but not an error object. You could do

    script.onerror = e => reject(new Error(e.message));

if you prefer, but you should always throw an error object.

src/util.js Outdated
Comment on lines 641 to 644
getUseElliptic: function() {
return config.use_indutny_elliptic;
},

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this function is really necessary - especially once you're only checking it in one place, you can just check

if (!config.use_indutny_elliptic) {

directly.

Then, in the test suite where you're checking this in a bunch of places, I'm not sure it's really necessary? We're never calling the test suite with config.use_indutny_elliptic = false, so it should always be available in the test suite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have this function, so I could avoid importing config in bunch of places. I think it is valid use-case.
Regarding tests, since we have option to disable elliptic, let's have test suite which would work with this option.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have this function, so I could avoid importing config in bunch of places.

That's why I mentioned "especially once you're only checking it in one place", because then you only have to import config in one place. I don't think that importing util instead of importing config is better, when it is config that you really need to check.

The test suite already uses config in lots of places, you could search for config in the test directory to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

src/config/config.js Outdated Show resolved Hide resolved
src/config/config.js Outdated Show resolved Hide resolved
src/lightweight_helper.js Outdated Show resolved Hide resolved
src/crypto/public_key/elliptic/indutnyKey.js Outdated Show resolved Hide resolved
@chesnokovilya chesnokovilya force-pushed the web-loading-testing branch 2 times, most recently from dfdb359 to f349e96 Compare October 15, 2019 13:26
chesnokovilya and others added 12 commits October 16, 2019 12:39
combined commits:

initial working nodeCrypto ecdh

clean up

Curve25519 key generation using tweetnacl.js

Move KeyPair.sign/verify to ecdsa.js

Move KeyPair.derive to ecdh.js

fix test, remove deprecated Buffer()

add only_constant_time_curves flag to config

ecdh is working after refactor

ecdsa webVerify is working

node signature verify is working without elliptic.

sign and verify are working for nodeCrypto

use build.config.js

renaming to build.env.js

fixing KeyPair constructor

wip: use grunt for lightweight build

add full-build to gruntfile to change from back from lightweight option

wip: grunt build --lightweigth is working now

refactored use of build.env, fixes ecdsa.sign function

WIP: fixed elliptic tests + add throw errors + use switch

solve problem with hash streaming using a hack

move toHash out of if/else

clean up in config and tests for full build

chnage travis unit test script

clean up

reverting changes to worker.min.js

moved throw on lightbuild to if

move to Array.From in ecdsa

add polyfill for Array.from

move toHash back to if/else - this would make lightbuild non-functional for streaming

remove polyfill array.from, and lightbuild to the gruntfile

remove double tests in travis.sh

init undutnyKeyPair only on demand. Change KeyPair format. Style fix

fixed tests

build correctly exclude elliptic in lightweight mode

add skiping non-working tests

fix gruntfile.js

add lightweight tag to tests

clean up

disabled some tests for lightbuild-webcrypto
We already have util.getFullBuild()
fix jwk key length error

load indutny/elliptic on demand in browser context

loading elliptic in browser functional

WIP new build file, use elliptic lib with prepare script

WIP: fix exclude elliptic build

WIP: lightweight build with node use correct path

WIP copy elliptic.min.js by grunt + almost working static elliptic download

WIP eslint fixes

add fix option to gruntfile eslint

load elliptic to window.openpgp.elliptic

add loadElliptic call to tests

fix brainpool test
@twiss twiss merged commit 08b7725 into openpgpjs:master Oct 25, 2019
twiss added a commit that referenced this pull request Nov 7, 2019
This was broken in #922 (merged as part of #956).

This would cause GPG to be unable to parse unencrypted secret keys,
thinking they were encrypted.

rfc4880bis-08 hints at this requirement, saying:

o  MPI of an integer representing the secret key, which is a scalar
   of the public EC point.

Since scalar multiplication happens after masking the private key,
this implies that we should serialize the private key after masking,
as well.
twiss added a commit that referenced this pull request Nov 7, 2019
This was broken in #922 (merged as part of #956).

This would cause GPG to be unable to parse unencrypted secret keys,
thinking they were encrypted.

rfc4880bis-08 hints at this requirement, saying:

o  MPI of an integer representing the secret key, which is a scalar
   of the public EC point.

Since scalar multiplication happens after masking the private key,
this implies that we should serialize the private key after masking,
as well.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants