mirror of
https://github.com/musix-org/musix-oss
synced 2025-06-17 01:16:00 +00:00
Modules
This commit is contained in:
133
node_modules/node-forge/CHANGELOG.md
generated
vendored
Normal file
133
node_modules/node-forge/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
Forge ChangeLog
|
||||
===============
|
||||
|
||||
## 0.7.4 - 2018-03-07
|
||||
|
||||
### Fixed
|
||||
- Potential regex denial of service in form.js.
|
||||
|
||||
### Added
|
||||
- Support for ED25519.
|
||||
- Support for baseN/base58.
|
||||
|
||||
## 0.7.3 - 2018-03-05
|
||||
|
||||
- Re-publish with npm 5.6.0 due to file timestamp issues.
|
||||
|
||||
## 0.7.2 - 2018-02-27
|
||||
|
||||
### Added
|
||||
- Support verification of SHA-384 certificates.
|
||||
- `1.2.840.10040.4.3'`/`dsa-with-sha1` OID.
|
||||
|
||||
### Fixed
|
||||
- Support importing PKCS#7 data with no certificates. RFC 2315 sec 9.1 states
|
||||
certificates are optional.
|
||||
- `asn1.equals` loop bug.
|
||||
- Fortuna implementation bugs.
|
||||
|
||||
## 0.7.1 - 2017-03-27
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix digestLength for hashes based on SHA-512.
|
||||
|
||||
## 0.7.0 - 2017-02-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix test looping bugs so all tests are run.
|
||||
- Improved ASN.1 parsing. Many failure cases eliminated. More sanity checks.
|
||||
Better behavior in default mode of parsing BIT STRINGs. Better handling of
|
||||
parsed BIT STRINGs in `toDer()`. More tests.
|
||||
- Improve X.509 BIT STRING handling by using new capture modes.
|
||||
|
||||
### Changed
|
||||
|
||||
- Major refactor to use CommonJS plus a browser build system.
|
||||
- Updated tests, examples, docs.
|
||||
- Updated dependencies.
|
||||
- Updated flash build system.
|
||||
- Improve OID mapping code.
|
||||
- Change test servers from Python to JavaScript.
|
||||
- Improve PhantomJS support.
|
||||
- Move Bower/bundle support to
|
||||
[forge-dist](https://github.com/digitalbazaar/forge-dist).
|
||||
- **BREAKING**: Require minimal digest algorithm dependencies from individual
|
||||
modules.
|
||||
- Enforce currently supported bit param values for byte buffer access. May be
|
||||
**BREAKING** for code that depended on unspecified and/or incorrect behavior.
|
||||
- Improve `asn1.prettyPrint()` BIT STRING display.
|
||||
|
||||
### Added
|
||||
|
||||
- webpack bundler support via `npm run build`:
|
||||
- Builds `.js`, `.min.js`, and basic sourcemaps.
|
||||
- Basic build: `forge.js`.
|
||||
- Build with extra utils and networking support: `forge.all.js`.
|
||||
- Build WebWorker support: `prime.worker.js`.
|
||||
- Browserify support in package.json.
|
||||
- Karma browser testing.
|
||||
- `forge.options` field.
|
||||
- `forge.options.usePureJavaScript` flag.
|
||||
- `forge.util.isNodejs` flag (used to select "native" APIs).
|
||||
- Run PhantomJS tests in Travis-CI.
|
||||
- Add "Donations" section to README.
|
||||
- Add IRC to "Contact" section of README.
|
||||
- Add "Security Considerations" section to README.
|
||||
- Add pbkdf2 usePureJavaScript test.
|
||||
- Add rsa.generateKeyPair async and usePureJavaScript tests.
|
||||
- Add .editorconfig support.
|
||||
- Add `md.all.js` which includes all digest algorithms.
|
||||
- Add asn1 `equals()` and `copy()`.
|
||||
- Add asn1 `validate()` capture options for BIT STRING contents and value.
|
||||
|
||||
### Removed
|
||||
|
||||
- **BREAKING**: Can no longer call `forge({...})` to create new instances.
|
||||
- Remove a large amount of old cruft.
|
||||
|
||||
### Migration from 0.6.x to 0.7.x
|
||||
|
||||
- (all) If you used the feature to create a new forge instance with new
|
||||
configuration options you will need to rework your code. That ability has
|
||||
been removed due to implementation complexity. The main rare use was to set
|
||||
the option to use pure JavaScript. That is now available as a library global
|
||||
flag `forge.options.usePureJavaScript`.
|
||||
- (npm,bower) If you used the default main file there is little to nothing to
|
||||
change.
|
||||
- (npm) If you accessed a sub-resource like `forge/js/pki` you should either
|
||||
switch to just using the main `forge` and access `forge.pki` or update to
|
||||
`forge/lib/pki`.
|
||||
- (bower) If you used a sub-resource like `forge/js/pki` you should switch to
|
||||
just using `forge` and access `forge.pki`. The bower release bundles
|
||||
everything in one minified file.
|
||||
- (bower) A configured workerScript like
|
||||
`/bower_components/forge/js/prime.worker.js` will need to change to
|
||||
`/bower_components/forge/dist/prime.worker.min.js`.
|
||||
- (all) If you used the networking support or flash socket support, you will
|
||||
need to use a custom build and/or adjust where files are loaded from. This
|
||||
functionality is not included in the bower distribution by default and is
|
||||
also now in a different directory.
|
||||
- (all) The library should now directly support building custom bundles with
|
||||
webpack, browserify, or similar.
|
||||
- (all) If building a custom bundle ensure the correct dependencies are
|
||||
included. In particular, note there is now a `md.all.js` file to include all
|
||||
digest algorithms. Individual files limit what they include by default to
|
||||
allow smaller custom builds. For instance, `pbdkf2.js` has a `sha1` default
|
||||
but does not include any algorithm files by default. This allows the
|
||||
possibility to include only `sha256` without the overhead of `sha1` and
|
||||
`sha512`.
|
||||
|
||||
### Notes
|
||||
|
||||
- This major update requires updating the version to 0.7.x. The existing
|
||||
work-in-progress "0.7.x" branch will be painfully rebased on top of this new
|
||||
0.7.x and moved forward to 0.8.x or later as needed.
|
||||
- 0.7.x is a start of simplifying forge based on common issues and what has
|
||||
appeared to be the most common usage. Please file issues with feedback if the
|
||||
changes are problematic for your use cases.
|
||||
|
||||
## 0.6.x - 2016 and earlier
|
||||
|
||||
- See Git commit log or https://github.com/digitalbazaar/forge.
|
331
node_modules/node-forge/LICENSE
generated
vendored
Normal file
331
node_modules/node-forge/LICENSE
generated
vendored
Normal file
@ -0,0 +1,331 @@
|
||||
You may use the Forge project under the terms of either the BSD License or the
|
||||
GNU General Public License (GPL) Version 2.
|
||||
|
||||
The BSD License is recommended for most projects. It is simple and easy to
|
||||
understand and it places almost no restrictions on what you can do with the
|
||||
Forge project.
|
||||
|
||||
If the GPL suits your project better you are also free to use Forge under
|
||||
that license.
|
||||
|
||||
You don't have to do anything special to choose one license or the other and
|
||||
you don't have to notify anyone which license you are using. You are free to
|
||||
use this project in commercial projects as long as the copyright header is
|
||||
left intact.
|
||||
|
||||
If you are a commercial entity and use this set of libraries in your
|
||||
commercial software then reasonable payment to Digital Bazaar, if you can
|
||||
afford it, is not required but is expected and would be appreciated. If this
|
||||
library saves you time, then it's saving you money. The cost of developing
|
||||
the Forge software was on the order of several hundred hours and tens of
|
||||
thousands of dollars. We are attempting to strike a balance between helping
|
||||
the development community while not being taken advantage of by lucrative
|
||||
commercial entities for our efforts.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
New BSD License (3-clause)
|
||||
Copyright (c) 2010, Digital Bazaar, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Digital Bazaar, Inc. nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL DIGITAL BAZAAR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
2095
node_modules/node-forge/README.md
generated
vendored
Normal file
2095
node_modules/node-forge/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
node_modules/node-forge/dist/forge.all.min.js
generated
vendored
Normal file
2
node_modules/node-forge/dist/forge.all.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/node-forge/dist/forge.all.min.js.map
generated
vendored
Normal file
1
node_modules/node-forge/dist/forge.all.min.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"forge.all.min.js","sources":["webpack:///forge.all.min.js"],"mappings":"AAAA","sourceRoot":""}
|
2
node_modules/node-forge/dist/forge.min.js
generated
vendored
Normal file
2
node_modules/node-forge/dist/forge.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/node-forge/dist/forge.min.js.map
generated
vendored
Normal file
1
node_modules/node-forge/dist/forge.min.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"forge.min.js","sources":["webpack:///forge.min.js"],"mappings":"AAAA","sourceRoot":""}
|
2
node_modules/node-forge/dist/prime.worker.min.js
generated
vendored
Normal file
2
node_modules/node-forge/dist/prime.worker.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/node-forge/dist/prime.worker.min.js.map
generated
vendored
Normal file
1
node_modules/node-forge/dist/prime.worker.min.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"prime.worker.min.js","sources":["webpack:///prime.worker.min.js"],"mappings":"AAAA","sourceRoot":""}
|
48
node_modules/node-forge/flash/README.md
generated
vendored
Normal file
48
node_modules/node-forge/flash/README.md
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
Forge Flash Support
|
||||
===================
|
||||
|
||||
SocketPool.swf
|
||||
--------------
|
||||
|
||||
Some special networking features can optionally use a Flash component.
|
||||
Building the output SWF file requires the [Flex SDK][]. A pre-built component
|
||||
is included: `swf/SocketPool.swf`.
|
||||
|
||||
Building the output SWF requires the `mxmlc` tool from the [Flex SDK][]. If
|
||||
that tools is already installed then look in the `package.json` file for the
|
||||
commands to rebuild it. If you need the SDK installed, there is a npm module that installs it:
|
||||
|
||||
npm install
|
||||
|
||||
To build a regular component:
|
||||
|
||||
npm run build
|
||||
|
||||
Additional debug support can be built in with the following:
|
||||
|
||||
npm run build-debug
|
||||
|
||||
Policy Server
|
||||
-------------
|
||||
|
||||
Flash support requires the use of a Policy Server.
|
||||
|
||||
### Apache Flash Socket Policy Module
|
||||
|
||||
[mod_fsp](./mod_fsp) provides an [Apache][] module that can serve up a Flash
|
||||
Socket Policy. See `mod_fsp/README` for more details. This module makes it easy
|
||||
to modify an [Apache][] server to allow cross domain requests to be made to it.
|
||||
|
||||
### Simple Python Policy Server
|
||||
|
||||
`policyserver.py` provides a very simple test policy server.
|
||||
|
||||
### Simple Node.js Policy Server
|
||||
|
||||
`policyserver.js` provides a very simple test policy server. If a server is
|
||||
needed for production environments, please use another option such as perhaps
|
||||
[nodejs_socket_policy_server][].
|
||||
|
||||
[Apache]: http://httpd.apache.org/
|
||||
[Flex SDK]: https://flex.apache.org/
|
||||
[nodejs_socket_policy_server]: https://github.com/bichinger/nodejs_socket_policy_server
|
BIN
node_modules/node-forge/flash/swf/SocketPool.swf
generated
vendored
Normal file
BIN
node_modules/node-forge/flash/swf/SocketPool.swf
generated
vendored
Normal file
Binary file not shown.
1091
node_modules/node-forge/lib/aes.js
generated
vendored
Normal file
1091
node_modules/node-forge/lib/aes.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
284
node_modules/node-forge/lib/aesCipherSuites.js
generated
vendored
Normal file
284
node_modules/node-forge/lib/aesCipherSuites.js
generated
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/**
|
||||
* A Javascript implementation of AES Cipher Suites for TLS.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2009-2015 Digital Bazaar, Inc.
|
||||
*
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./aes');
|
||||
require('./tls');
|
||||
|
||||
var tls = module.exports = forge.tls;
|
||||
|
||||
/**
|
||||
* Supported cipher suites.
|
||||
*/
|
||||
tls.CipherSuites['TLS_RSA_WITH_AES_128_CBC_SHA'] = {
|
||||
id: [0x00,0x2f],
|
||||
name: 'TLS_RSA_WITH_AES_128_CBC_SHA',
|
||||
initSecurityParameters: function(sp) {
|
||||
sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes;
|
||||
sp.cipher_type = tls.CipherType.block;
|
||||
sp.enc_key_length = 16;
|
||||
sp.block_length = 16;
|
||||
sp.fixed_iv_length = 16;
|
||||
sp.record_iv_length = 16;
|
||||
sp.mac_algorithm = tls.MACAlgorithm.hmac_sha1;
|
||||
sp.mac_length = 20;
|
||||
sp.mac_key_length = 20;
|
||||
},
|
||||
initConnectionState: initConnectionState
|
||||
};
|
||||
tls.CipherSuites['TLS_RSA_WITH_AES_256_CBC_SHA'] = {
|
||||
id: [0x00,0x35],
|
||||
name: 'TLS_RSA_WITH_AES_256_CBC_SHA',
|
||||
initSecurityParameters: function(sp) {
|
||||
sp.bulk_cipher_algorithm = tls.BulkCipherAlgorithm.aes;
|
||||
sp.cipher_type = tls.CipherType.block;
|
||||
sp.enc_key_length = 32;
|
||||
sp.block_length = 16;
|
||||
sp.fixed_iv_length = 16;
|
||||
sp.record_iv_length = 16;
|
||||
sp.mac_algorithm = tls.MACAlgorithm.hmac_sha1;
|
||||
sp.mac_length = 20;
|
||||
sp.mac_key_length = 20;
|
||||
},
|
||||
initConnectionState: initConnectionState
|
||||
};
|
||||
|
||||
function initConnectionState(state, c, sp) {
|
||||
var client = (c.entity === forge.tls.ConnectionEnd.client);
|
||||
|
||||
// cipher setup
|
||||
state.read.cipherState = {
|
||||
init: false,
|
||||
cipher: forge.cipher.createDecipher('AES-CBC', client ?
|
||||
sp.keys.server_write_key : sp.keys.client_write_key),
|
||||
iv: client ? sp.keys.server_write_IV : sp.keys.client_write_IV
|
||||
};
|
||||
state.write.cipherState = {
|
||||
init: false,
|
||||
cipher: forge.cipher.createCipher('AES-CBC', client ?
|
||||
sp.keys.client_write_key : sp.keys.server_write_key),
|
||||
iv: client ? sp.keys.client_write_IV : sp.keys.server_write_IV
|
||||
};
|
||||
state.read.cipherFunction = decrypt_aes_cbc_sha1;
|
||||
state.write.cipherFunction = encrypt_aes_cbc_sha1;
|
||||
|
||||
// MAC setup
|
||||
state.read.macLength = state.write.macLength = sp.mac_length;
|
||||
state.read.macFunction = state.write.macFunction = tls.hmac_sha1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the TLSCompressed record into a TLSCipherText record using AES
|
||||
* in CBC mode.
|
||||
*
|
||||
* @param record the TLSCompressed record to encrypt.
|
||||
* @param s the ConnectionState to use.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
function encrypt_aes_cbc_sha1(record, s) {
|
||||
var rval = false;
|
||||
|
||||
// append MAC to fragment, update sequence number
|
||||
var mac = s.macFunction(s.macKey, s.sequenceNumber, record);
|
||||
record.fragment.putBytes(mac);
|
||||
s.updateSequenceNumber();
|
||||
|
||||
// TLS 1.1+ use an explicit IV every time to protect against CBC attacks
|
||||
var iv;
|
||||
if(record.version.minor === tls.Versions.TLS_1_0.minor) {
|
||||
// use the pre-generated IV when initializing for TLS 1.0, otherwise use
|
||||
// the residue from the previous encryption
|
||||
iv = s.cipherState.init ? null : s.cipherState.iv;
|
||||
} else {
|
||||
iv = forge.random.getBytesSync(16);
|
||||
}
|
||||
|
||||
s.cipherState.init = true;
|
||||
|
||||
// start cipher
|
||||
var cipher = s.cipherState.cipher;
|
||||
cipher.start({iv: iv});
|
||||
|
||||
// TLS 1.1+ write IV into output
|
||||
if(record.version.minor >= tls.Versions.TLS_1_1.minor) {
|
||||
cipher.output.putBytes(iv);
|
||||
}
|
||||
|
||||
// do encryption (default padding is appropriate)
|
||||
cipher.update(record.fragment);
|
||||
if(cipher.finish(encrypt_aes_cbc_sha1_padding)) {
|
||||
// set record fragment to encrypted output
|
||||
record.fragment = cipher.output;
|
||||
record.length = record.fragment.length();
|
||||
rval = true;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles padding for aes_cbc_sha1 in encrypt mode.
|
||||
*
|
||||
* @param blockSize the block size.
|
||||
* @param input the input buffer.
|
||||
* @param decrypt true in decrypt mode, false in encrypt mode.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
function encrypt_aes_cbc_sha1_padding(blockSize, input, decrypt) {
|
||||
/* The encrypted data length (TLSCiphertext.length) is one more than the sum
|
||||
of SecurityParameters.block_length, TLSCompressed.length,
|
||||
SecurityParameters.mac_length, and padding_length.
|
||||
|
||||
The padding may be any length up to 255 bytes long, as long as it results in
|
||||
the TLSCiphertext.length being an integral multiple of the block length.
|
||||
Lengths longer than necessary might be desirable to frustrate attacks on a
|
||||
protocol based on analysis of the lengths of exchanged messages. Each uint8
|
||||
in the padding data vector must be filled with the padding length value.
|
||||
|
||||
The padding length should be such that the total size of the
|
||||
GenericBlockCipher structure is a multiple of the cipher's block length.
|
||||
Legal values range from zero to 255, inclusive. This length specifies the
|
||||
length of the padding field exclusive of the padding_length field itself.
|
||||
|
||||
This is slightly different from PKCS#7 because the padding value is 1
|
||||
less than the actual number of padding bytes if you include the
|
||||
padding_length uint8 itself as a padding byte. */
|
||||
if(!decrypt) {
|
||||
// get the number of padding bytes required to reach the blockSize and
|
||||
// subtract 1 for the padding value (to make room for the padding_length
|
||||
// uint8)
|
||||
var padding = blockSize - (input.length() % blockSize);
|
||||
input.fillWithByte(padding - 1, padding);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles padding for aes_cbc_sha1 in decrypt mode.
|
||||
*
|
||||
* @param blockSize the block size.
|
||||
* @param output the output buffer.
|
||||
* @param decrypt true in decrypt mode, false in encrypt mode.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
function decrypt_aes_cbc_sha1_padding(blockSize, output, decrypt) {
|
||||
var rval = true;
|
||||
if(decrypt) {
|
||||
/* The last byte in the output specifies the number of padding bytes not
|
||||
including itself. Each of the padding bytes has the same value as that
|
||||
last byte (known as the padding_length). Here we check all padding
|
||||
bytes to ensure they have the value of padding_length even if one of
|
||||
them is bad in order to ward-off timing attacks. */
|
||||
var len = output.length();
|
||||
var paddingLength = output.last();
|
||||
for(var i = len - 1 - paddingLength; i < len - 1; ++i) {
|
||||
rval = rval && (output.at(i) == paddingLength);
|
||||
}
|
||||
if(rval) {
|
||||
// trim off padding bytes and last padding length byte
|
||||
output.truncate(paddingLength + 1);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a TLSCipherText record into a TLSCompressed record using
|
||||
* AES in CBC mode.
|
||||
*
|
||||
* @param record the TLSCipherText record to decrypt.
|
||||
* @param s the ConnectionState to use.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
var count = 0;
|
||||
function decrypt_aes_cbc_sha1(record, s) {
|
||||
var rval = false;
|
||||
++count;
|
||||
|
||||
var iv;
|
||||
if(record.version.minor === tls.Versions.TLS_1_0.minor) {
|
||||
// use pre-generated IV when initializing for TLS 1.0, otherwise use the
|
||||
// residue from the previous decryption
|
||||
iv = s.cipherState.init ? null : s.cipherState.iv;
|
||||
} else {
|
||||
// TLS 1.1+ use an explicit IV every time to protect against CBC attacks
|
||||
// that is appended to the record fragment
|
||||
iv = record.fragment.getBytes(16);
|
||||
}
|
||||
|
||||
s.cipherState.init = true;
|
||||
|
||||
// start cipher
|
||||
var cipher = s.cipherState.cipher;
|
||||
cipher.start({iv: iv});
|
||||
|
||||
// do decryption
|
||||
cipher.update(record.fragment);
|
||||
rval = cipher.finish(decrypt_aes_cbc_sha1_padding);
|
||||
|
||||
// even if decryption fails, keep going to minimize timing attacks
|
||||
|
||||
// decrypted data:
|
||||
// first (len - 20) bytes = application data
|
||||
// last 20 bytes = MAC
|
||||
var macLen = s.macLength;
|
||||
|
||||
// create a random MAC to check against should the mac length check fail
|
||||
// Note: do this regardless of the failure to keep timing consistent
|
||||
var mac = forge.random.getBytesSync(macLen);
|
||||
|
||||
// get fragment and mac
|
||||
var len = cipher.output.length();
|
||||
if(len >= macLen) {
|
||||
record.fragment = cipher.output.getBytes(len - macLen);
|
||||
mac = cipher.output.getBytes(macLen);
|
||||
} else {
|
||||
// bad data, but get bytes anyway to try to keep timing consistent
|
||||
record.fragment = cipher.output.getBytes();
|
||||
}
|
||||
record.fragment = forge.util.createBuffer(record.fragment);
|
||||
record.length = record.fragment.length();
|
||||
|
||||
// see if data integrity checks out, update sequence number
|
||||
var mac2 = s.macFunction(s.macKey, s.sequenceNumber, record);
|
||||
s.updateSequenceNumber();
|
||||
rval = compareMacs(s.macKey, mac, mac2) && rval;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely compare two MACs. This function will compare two MACs in a way
|
||||
* that protects against timing attacks.
|
||||
*
|
||||
* TODO: Expose elsewhere as a utility API.
|
||||
*
|
||||
* See: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/
|
||||
*
|
||||
* @param key the MAC key to use.
|
||||
* @param mac1 as a binary-encoded string of bytes.
|
||||
* @param mac2 as a binary-encoded string of bytes.
|
||||
*
|
||||
* @return true if the MACs are the same, false if not.
|
||||
*/
|
||||
function compareMacs(key, mac1, mac2) {
|
||||
var hmac = forge.hmac.create();
|
||||
|
||||
hmac.start('SHA1', key);
|
||||
hmac.update(mac1);
|
||||
mac1 = hmac.digest().getBytes();
|
||||
|
||||
hmac.start(null, null);
|
||||
hmac.update(mac2);
|
||||
mac2 = hmac.digest().getBytes();
|
||||
|
||||
return mac1 === mac2;
|
||||
}
|
1408
node_modules/node-forge/lib/asn1.js
generated
vendored
Normal file
1408
node_modules/node-forge/lib/asn1.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
186
node_modules/node-forge/lib/baseN.js
generated
vendored
Normal file
186
node_modules/node-forge/lib/baseN.js
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
/**
|
||||
* Base-N/Base-X encoding/decoding functions.
|
||||
*
|
||||
* Original implementation from base-x:
|
||||
* https://github.com/cryptocoinjs/base-x
|
||||
*
|
||||
* Which is MIT licensed:
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright base-x contributors (c) 2016
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
var api = {};
|
||||
module.exports = api;
|
||||
|
||||
// baseN alphabet indexes
|
||||
var _reverseAlphabets = {};
|
||||
|
||||
/**
|
||||
* BaseN-encodes a Uint8Array using the given alphabet.
|
||||
*
|
||||
* @param input the Uint8Array to encode.
|
||||
* @param maxline the maximum number of encoded characters per line to use,
|
||||
* defaults to none.
|
||||
*
|
||||
* @return the baseN-encoded output string.
|
||||
*/
|
||||
api.encode = function(input, alphabet, maxline) {
|
||||
if(typeof alphabet !== 'string') {
|
||||
throw new TypeError('"alphabet" must be a string.');
|
||||
}
|
||||
if(maxline !== undefined && typeof maxline !== 'number') {
|
||||
throw new TypeError('"maxline" must be a number.');
|
||||
}
|
||||
|
||||
var output = '';
|
||||
|
||||
if(!(input instanceof Uint8Array)) {
|
||||
// assume forge byte buffer
|
||||
output = _encodeWithByteBuffer(input, alphabet);
|
||||
} else {
|
||||
var i = 0;
|
||||
var base = alphabet.length;
|
||||
var first = alphabet.charAt(0);
|
||||
var digits = [0];
|
||||
for(i = 0; i < input.length; ++i) {
|
||||
for(var j = 0, carry = input[i]; j < digits.length; ++j) {
|
||||
carry += digits[j] << 8;
|
||||
digits[j] = carry % base;
|
||||
carry = (carry / base) | 0;
|
||||
}
|
||||
|
||||
while(carry > 0) {
|
||||
digits.push(carry % base);
|
||||
carry = (carry / base) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
// deal with leading zeros
|
||||
for(i = 0; input[i] === 0 && i < input.length - 1; ++i) {
|
||||
output += first;
|
||||
}
|
||||
// convert digits to a string
|
||||
for(i = digits.length - 1; i >= 0; --i) {
|
||||
output += alphabet[digits[i]];
|
||||
}
|
||||
}
|
||||
|
||||
if(maxline) {
|
||||
var regex = new RegExp('.{1,' + maxline + '}', 'g');
|
||||
output = output.match(regex).join('\r\n');
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes a baseN-encoded (using the given alphabet) string to a
|
||||
* Uint8Array.
|
||||
*
|
||||
* @param input the baseN-encoded input string.
|
||||
*
|
||||
* @return the Uint8Array.
|
||||
*/
|
||||
api.decode = function(input, alphabet) {
|
||||
if(typeof input !== 'string') {
|
||||
throw new TypeError('"input" must be a string.');
|
||||
}
|
||||
if(typeof alphabet !== 'string') {
|
||||
throw new TypeError('"alphabet" must be a string.');
|
||||
}
|
||||
|
||||
var table = _reverseAlphabets[alphabet];
|
||||
if(!table) {
|
||||
// compute reverse alphabet
|
||||
table = _reverseAlphabets[alphabet] = [];
|
||||
for(var i = 0; i < alphabet.length; ++i) {
|
||||
table[alphabet.charCodeAt(i)] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// remove whitespace characters
|
||||
input = input.replace(/\s/g, '');
|
||||
|
||||
var base = alphabet.length;
|
||||
var first = alphabet.charAt(0);
|
||||
var bytes = [0];
|
||||
for(var i = 0; i < input.length; i++) {
|
||||
var value = table[input.charCodeAt(i)];
|
||||
if(value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(var j = 0, carry = value; j < bytes.length; ++j) {
|
||||
carry += bytes[j] * base;
|
||||
bytes[j] = carry & 0xff;
|
||||
carry >>= 8;
|
||||
}
|
||||
|
||||
while(carry > 0) {
|
||||
bytes.push(carry & 0xff);
|
||||
carry >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// deal with leading zeros
|
||||
for(var k = 0; input[k] === first && k < input.length - 1; ++k) {
|
||||
bytes.push(0);
|
||||
}
|
||||
|
||||
if(typeof Buffer !== 'undefined') {
|
||||
return Buffer.from(bytes.reverse());
|
||||
}
|
||||
|
||||
return new Uint8Array(bytes.reverse());
|
||||
};
|
||||
|
||||
function _encodeWithByteBuffer(input, alphabet) {
|
||||
var i = 0;
|
||||
var base = alphabet.length;
|
||||
var first = alphabet.charAt(0);
|
||||
var digits = [0];
|
||||
for(i = 0; i < input.length(); ++i) {
|
||||
for(var j = 0, carry = input.at(i); j < digits.length; ++j) {
|
||||
carry += digits[j] << 8;
|
||||
digits[j] = carry % base;
|
||||
carry = (carry / base) | 0;
|
||||
}
|
||||
|
||||
while(carry > 0) {
|
||||
digits.push(carry % base);
|
||||
carry = (carry / base) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
var output = '';
|
||||
|
||||
// deal with leading zeros
|
||||
for(i = 0; input.at(i) === 0 && i < input.length() - 1; ++i) {
|
||||
output += first;
|
||||
}
|
||||
// convert digits to a string
|
||||
for(i = digits.length - 1; i >= 0; --i) {
|
||||
output += alphabet[digits[i]];
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
230
node_modules/node-forge/lib/cipher.js
generated
vendored
Normal file
230
node_modules/node-forge/lib/cipher.js
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Cipher base API.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
module.exports = forge.cipher = forge.cipher || {};
|
||||
|
||||
// registered algorithms
|
||||
forge.cipher.algorithms = forge.cipher.algorithms || {};
|
||||
|
||||
/**
|
||||
* Creates a cipher object that can be used to encrypt data using the given
|
||||
* algorithm and key. The algorithm may be provided as a string value for a
|
||||
* previously registered algorithm or it may be given as a cipher algorithm
|
||||
* API object.
|
||||
*
|
||||
* @param algorithm the algorithm to use, either a string or an algorithm API
|
||||
* object.
|
||||
* @param key the key to use, as a binary-encoded string of bytes or a
|
||||
* byte buffer.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.cipher.createCipher = function(algorithm, key) {
|
||||
var api = algorithm;
|
||||
if(typeof api === 'string') {
|
||||
api = forge.cipher.getAlgorithm(api);
|
||||
if(api) {
|
||||
api = api();
|
||||
}
|
||||
}
|
||||
if(!api) {
|
||||
throw new Error('Unsupported algorithm: ' + algorithm);
|
||||
}
|
||||
|
||||
// assume block cipher
|
||||
return new forge.cipher.BlockCipher({
|
||||
algorithm: api,
|
||||
key: key,
|
||||
decrypt: false
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a decipher object that can be used to decrypt data using the given
|
||||
* algorithm and key. The algorithm may be provided as a string value for a
|
||||
* previously registered algorithm or it may be given as a cipher algorithm
|
||||
* API object.
|
||||
*
|
||||
* @param algorithm the algorithm to use, either a string or an algorithm API
|
||||
* object.
|
||||
* @param key the key to use, as a binary-encoded string of bytes or a
|
||||
* byte buffer.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.cipher.createDecipher = function(algorithm, key) {
|
||||
var api = algorithm;
|
||||
if(typeof api === 'string') {
|
||||
api = forge.cipher.getAlgorithm(api);
|
||||
if(api) {
|
||||
api = api();
|
||||
}
|
||||
}
|
||||
if(!api) {
|
||||
throw new Error('Unsupported algorithm: ' + algorithm);
|
||||
}
|
||||
|
||||
// assume block cipher
|
||||
return new forge.cipher.BlockCipher({
|
||||
algorithm: api,
|
||||
key: key,
|
||||
decrypt: true
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers an algorithm by name. If the name was already registered, the
|
||||
* algorithm API object will be overwritten.
|
||||
*
|
||||
* @param name the name of the algorithm.
|
||||
* @param algorithm the algorithm API object.
|
||||
*/
|
||||
forge.cipher.registerAlgorithm = function(name, algorithm) {
|
||||
name = name.toUpperCase();
|
||||
forge.cipher.algorithms[name] = algorithm;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a registered algorithm by name.
|
||||
*
|
||||
* @param name the name of the algorithm.
|
||||
*
|
||||
* @return the algorithm, if found, null if not.
|
||||
*/
|
||||
forge.cipher.getAlgorithm = function(name) {
|
||||
name = name.toUpperCase();
|
||||
if(name in forge.cipher.algorithms) {
|
||||
return forge.cipher.algorithms[name];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var BlockCipher = forge.cipher.BlockCipher = function(options) {
|
||||
this.algorithm = options.algorithm;
|
||||
this.mode = this.algorithm.mode;
|
||||
this.blockSize = this.mode.blockSize;
|
||||
this._finish = false;
|
||||
this._input = null;
|
||||
this.output = null;
|
||||
this._op = options.decrypt ? this.mode.decrypt : this.mode.encrypt;
|
||||
this._decrypt = options.decrypt;
|
||||
this.algorithm.initialize(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts or restarts the encryption or decryption process, whichever
|
||||
* was previously configured.
|
||||
*
|
||||
* For non-GCM mode, the IV may be a binary-encoded string of bytes, an array
|
||||
* of bytes, a byte buffer, or an array of 32-bit integers. If the IV is in
|
||||
* bytes, then it must be Nb (16) bytes in length. If the IV is given in as
|
||||
* 32-bit integers, then it must be 4 integers long.
|
||||
*
|
||||
* Note: an IV is not required or used in ECB mode.
|
||||
*
|
||||
* For GCM-mode, the IV must be given as a binary-encoded string of bytes or
|
||||
* a byte buffer. The number of bytes should be 12 (96 bits) as recommended
|
||||
* by NIST SP-800-38D but another length may be given.
|
||||
*
|
||||
* @param options the options to use:
|
||||
* iv the initialization vector to use as a binary-encoded string of
|
||||
* bytes, null to reuse the last ciphered block from a previous
|
||||
* update() (this "residue" method is for legacy support only).
|
||||
* additionalData additional authentication data as a binary-encoded
|
||||
* string of bytes, for 'GCM' mode, (default: none).
|
||||
* tagLength desired length of authentication tag, in bits, for
|
||||
* 'GCM' mode (0-128, default: 128).
|
||||
* tag the authentication tag to check if decrypting, as a
|
||||
* binary-encoded string of bytes.
|
||||
* output the output the buffer to write to, null to create one.
|
||||
*/
|
||||
BlockCipher.prototype.start = function(options) {
|
||||
options = options || {};
|
||||
var opts = {};
|
||||
for(var key in options) {
|
||||
opts[key] = options[key];
|
||||
}
|
||||
opts.decrypt = this._decrypt;
|
||||
this._finish = false;
|
||||
this._input = forge.util.createBuffer();
|
||||
this.output = options.output || forge.util.createBuffer();
|
||||
this.mode.start(opts);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the next block according to the cipher mode.
|
||||
*
|
||||
* @param input the buffer to read from.
|
||||
*/
|
||||
BlockCipher.prototype.update = function(input) {
|
||||
if(input) {
|
||||
// input given, so empty it into the input buffer
|
||||
this._input.putBuffer(input);
|
||||
}
|
||||
|
||||
// do cipher operation until it needs more input and not finished
|
||||
while(!this._op.call(this.mode, this._input, this.output, this._finish) &&
|
||||
!this._finish) {}
|
||||
|
||||
// free consumed memory from input buffer
|
||||
this._input.compact();
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes encrypting or decrypting.
|
||||
*
|
||||
* @param pad a padding function to use in CBC mode, null for default,
|
||||
* signature(blockSize, buffer, decrypt).
|
||||
*
|
||||
* @return true if successful, false on error.
|
||||
*/
|
||||
BlockCipher.prototype.finish = function(pad) {
|
||||
// backwards-compatibility w/deprecated padding API
|
||||
// Note: will overwrite padding functions even after another start() call
|
||||
if(pad && (this.mode.name === 'ECB' || this.mode.name === 'CBC')) {
|
||||
this.mode.pad = function(input) {
|
||||
return pad(this.blockSize, input, false);
|
||||
};
|
||||
this.mode.unpad = function(output) {
|
||||
return pad(this.blockSize, output, true);
|
||||
};
|
||||
}
|
||||
|
||||
// build options for padding and afterFinish functions
|
||||
var options = {};
|
||||
options.decrypt = this._decrypt;
|
||||
|
||||
// get # of bytes that won't fill a block
|
||||
options.overflow = this._input.length() % this.blockSize;
|
||||
|
||||
if(!this._decrypt && this.mode.pad) {
|
||||
if(!this.mode.pad(this._input, options)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// do final update
|
||||
this._finish = true;
|
||||
this.update();
|
||||
|
||||
if(this._decrypt && this.mode.unpad) {
|
||||
if(!this.mode.unpad(this.output, options)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(this.mode.afterFinish) {
|
||||
if(!this.mode.afterFinish(this.output, options)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
987
node_modules/node-forge/lib/cipherModes.js
generated
vendored
Normal file
987
node_modules/node-forge/lib/cipherModes.js
generated
vendored
Normal file
@ -0,0 +1,987 @@
|
||||
/**
|
||||
* Supported cipher modes.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
forge.cipher = forge.cipher || {};
|
||||
|
||||
// supported cipher modes
|
||||
var modes = module.exports = forge.cipher.modes = forge.cipher.modes || {};
|
||||
|
||||
/** Electronic codebook (ECB) (Don't use this; it's not secure) **/
|
||||
|
||||
modes.ecb = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'ECB';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = new Array(this._ints);
|
||||
this._outBlock = new Array(this._ints);
|
||||
};
|
||||
|
||||
modes.ecb.prototype.start = function(options) {};
|
||||
|
||||
modes.ecb.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get next block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = input.getInt32();
|
||||
}
|
||||
|
||||
// encrypt block
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// write output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._outBlock[i]);
|
||||
}
|
||||
};
|
||||
|
||||
modes.ecb.prototype.decrypt = function(input, output, finish) {
|
||||
// not enough input to decrypt
|
||||
if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get next block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = input.getInt32();
|
||||
}
|
||||
|
||||
// decrypt block
|
||||
this.cipher.decrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// write output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._outBlock[i]);
|
||||
}
|
||||
};
|
||||
|
||||
modes.ecb.prototype.pad = function(input, options) {
|
||||
// add PKCS#7 padding to block (each pad byte is the
|
||||
// value of the number of pad bytes)
|
||||
var padding = (input.length() === this.blockSize ?
|
||||
this.blockSize : (this.blockSize - input.length()));
|
||||
input.fillWithByte(padding, padding);
|
||||
return true;
|
||||
};
|
||||
|
||||
modes.ecb.prototype.unpad = function(output, options) {
|
||||
// check for error: input data not a multiple of blockSize
|
||||
if(options.overflow > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ensure padding byte count is valid
|
||||
var len = output.length();
|
||||
var count = output.at(len - 1);
|
||||
if(count > (this.blockSize << 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim off padding bytes
|
||||
output.truncate(count);
|
||||
return true;
|
||||
};
|
||||
|
||||
/** Cipher-block Chaining (CBC) **/
|
||||
|
||||
modes.cbc = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'CBC';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = new Array(this._ints);
|
||||
this._outBlock = new Array(this._ints);
|
||||
};
|
||||
|
||||
modes.cbc.prototype.start = function(options) {
|
||||
// Note: legacy support for using IV residue (has security flaws)
|
||||
// if IV is null, reuse block from previous processing
|
||||
if(options.iv === null) {
|
||||
// must have a previous block
|
||||
if(!this._prev) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
}
|
||||
this._iv = this._prev.slice(0);
|
||||
} else if(!('iv' in options)) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
} else {
|
||||
// save IV as "previous" block
|
||||
this._iv = transformIV(options.iv);
|
||||
this._prev = this._iv.slice(0);
|
||||
}
|
||||
};
|
||||
|
||||
modes.cbc.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get next block
|
||||
// CBC XOR's IV (or previous block) with plaintext
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = this._prev[i] ^ input.getInt32();
|
||||
}
|
||||
|
||||
// encrypt block
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// write output, save previous block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._outBlock[i]);
|
||||
}
|
||||
this._prev = this._outBlock;
|
||||
};
|
||||
|
||||
modes.cbc.prototype.decrypt = function(input, output, finish) {
|
||||
// not enough input to decrypt
|
||||
if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get next block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = input.getInt32();
|
||||
}
|
||||
|
||||
// decrypt block
|
||||
this.cipher.decrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// write output, save previous ciphered block
|
||||
// CBC XOR's IV (or previous block) with ciphertext
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._prev[i] ^ this._outBlock[i]);
|
||||
}
|
||||
this._prev = this._inBlock.slice(0);
|
||||
};
|
||||
|
||||
modes.cbc.prototype.pad = function(input, options) {
|
||||
// add PKCS#7 padding to block (each pad byte is the
|
||||
// value of the number of pad bytes)
|
||||
var padding = (input.length() === this.blockSize ?
|
||||
this.blockSize : (this.blockSize - input.length()));
|
||||
input.fillWithByte(padding, padding);
|
||||
return true;
|
||||
};
|
||||
|
||||
modes.cbc.prototype.unpad = function(output, options) {
|
||||
// check for error: input data not a multiple of blockSize
|
||||
if(options.overflow > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ensure padding byte count is valid
|
||||
var len = output.length();
|
||||
var count = output.at(len - 1);
|
||||
if(count > (this.blockSize << 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim off padding bytes
|
||||
output.truncate(count);
|
||||
return true;
|
||||
};
|
||||
|
||||
/** Cipher feedback (CFB) **/
|
||||
|
||||
modes.cfb = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'CFB';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = null;
|
||||
this._outBlock = new Array(this._ints);
|
||||
this._partialBlock = new Array(this._ints);
|
||||
this._partialOutput = forge.util.createBuffer();
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.cfb.prototype.start = function(options) {
|
||||
if(!('iv' in options)) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
}
|
||||
// use IV as first input
|
||||
this._iv = transformIV(options.iv);
|
||||
this._inBlock = this._iv.slice(0);
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.cfb.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
var inputLength = input.length();
|
||||
if(inputLength === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// handle full block
|
||||
if(this._partialBytes === 0 && inputLength >= this.blockSize) {
|
||||
// XOR input with output, write input as output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = input.getInt32() ^ this._outBlock[i];
|
||||
output.putInt32(this._inBlock[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// handle partial block
|
||||
var partialBytes = (this.blockSize - inputLength) % this.blockSize;
|
||||
if(partialBytes > 0) {
|
||||
partialBytes = this.blockSize - partialBytes;
|
||||
}
|
||||
|
||||
// XOR input with output, write input as partial output
|
||||
this._partialOutput.clear();
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._partialBlock[i] = input.getInt32() ^ this._outBlock[i];
|
||||
this._partialOutput.putInt32(this._partialBlock[i]);
|
||||
}
|
||||
|
||||
if(partialBytes > 0) {
|
||||
// block still incomplete, restore input buffer
|
||||
input.read -= this.blockSize;
|
||||
} else {
|
||||
// block complete, update input block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = this._partialBlock[i];
|
||||
}
|
||||
}
|
||||
|
||||
// skip any previous partial bytes
|
||||
if(this._partialBytes > 0) {
|
||||
this._partialOutput.getBytes(this._partialBytes);
|
||||
}
|
||||
|
||||
if(partialBytes > 0 && !finish) {
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
partialBytes - this._partialBytes));
|
||||
this._partialBytes = partialBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
inputLength - this._partialBytes));
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.cfb.prototype.decrypt = function(input, output, finish) {
|
||||
// not enough input to decrypt
|
||||
var inputLength = input.length();
|
||||
if(inputLength === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block (CFB always uses encryption mode)
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// handle full block
|
||||
if(this._partialBytes === 0 && inputLength >= this.blockSize) {
|
||||
// XOR input with output, write input as output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = input.getInt32();
|
||||
output.putInt32(this._inBlock[i] ^ this._outBlock[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// handle partial block
|
||||
var partialBytes = (this.blockSize - inputLength) % this.blockSize;
|
||||
if(partialBytes > 0) {
|
||||
partialBytes = this.blockSize - partialBytes;
|
||||
}
|
||||
|
||||
// XOR input with output, write input as partial output
|
||||
this._partialOutput.clear();
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._partialBlock[i] = input.getInt32();
|
||||
this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]);
|
||||
}
|
||||
|
||||
if(partialBytes > 0) {
|
||||
// block still incomplete, restore input buffer
|
||||
input.read -= this.blockSize;
|
||||
} else {
|
||||
// block complete, update input block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = this._partialBlock[i];
|
||||
}
|
||||
}
|
||||
|
||||
// skip any previous partial bytes
|
||||
if(this._partialBytes > 0) {
|
||||
this._partialOutput.getBytes(this._partialBytes);
|
||||
}
|
||||
|
||||
if(partialBytes > 0 && !finish) {
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
partialBytes - this._partialBytes));
|
||||
this._partialBytes = partialBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
inputLength - this._partialBytes));
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
/** Output feedback (OFB) **/
|
||||
|
||||
modes.ofb = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'OFB';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = null;
|
||||
this._outBlock = new Array(this._ints);
|
||||
this._partialOutput = forge.util.createBuffer();
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.ofb.prototype.start = function(options) {
|
||||
if(!('iv' in options)) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
}
|
||||
// use IV as first input
|
||||
this._iv = transformIV(options.iv);
|
||||
this._inBlock = this._iv.slice(0);
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.ofb.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
var inputLength = input.length();
|
||||
if(input.length() === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block (OFB always uses encryption mode)
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// handle full block
|
||||
if(this._partialBytes === 0 && inputLength >= this.blockSize) {
|
||||
// XOR input with output and update next input
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(input.getInt32() ^ this._outBlock[i]);
|
||||
this._inBlock[i] = this._outBlock[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// handle partial block
|
||||
var partialBytes = (this.blockSize - inputLength) % this.blockSize;
|
||||
if(partialBytes > 0) {
|
||||
partialBytes = this.blockSize - partialBytes;
|
||||
}
|
||||
|
||||
// XOR input with output
|
||||
this._partialOutput.clear();
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
|
||||
}
|
||||
|
||||
if(partialBytes > 0) {
|
||||
// block still incomplete, restore input buffer
|
||||
input.read -= this.blockSize;
|
||||
} else {
|
||||
// block complete, update input block
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._inBlock[i] = this._outBlock[i];
|
||||
}
|
||||
}
|
||||
|
||||
// skip any previous partial bytes
|
||||
if(this._partialBytes > 0) {
|
||||
this._partialOutput.getBytes(this._partialBytes);
|
||||
}
|
||||
|
||||
if(partialBytes > 0 && !finish) {
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
partialBytes - this._partialBytes));
|
||||
this._partialBytes = partialBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
inputLength - this._partialBytes));
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.ofb.prototype.decrypt = modes.ofb.prototype.encrypt;
|
||||
|
||||
/** Counter (CTR) **/
|
||||
|
||||
modes.ctr = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'CTR';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = null;
|
||||
this._outBlock = new Array(this._ints);
|
||||
this._partialOutput = forge.util.createBuffer();
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.ctr.prototype.start = function(options) {
|
||||
if(!('iv' in options)) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
}
|
||||
// use IV as first input
|
||||
this._iv = transformIV(options.iv);
|
||||
this._inBlock = this._iv.slice(0);
|
||||
this._partialBytes = 0;
|
||||
};
|
||||
|
||||
modes.ctr.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
var inputLength = input.length();
|
||||
if(inputLength === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block (CTR always uses encryption mode)
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// handle full block
|
||||
if(this._partialBytes === 0 && inputLength >= this.blockSize) {
|
||||
// XOR input with output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(input.getInt32() ^ this._outBlock[i]);
|
||||
}
|
||||
} else {
|
||||
// handle partial block
|
||||
var partialBytes = (this.blockSize - inputLength) % this.blockSize;
|
||||
if(partialBytes > 0) {
|
||||
partialBytes = this.blockSize - partialBytes;
|
||||
}
|
||||
|
||||
// XOR input with output
|
||||
this._partialOutput.clear();
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
|
||||
}
|
||||
|
||||
if(partialBytes > 0) {
|
||||
// block still incomplete, restore input buffer
|
||||
input.read -= this.blockSize;
|
||||
}
|
||||
|
||||
// skip any previous partial bytes
|
||||
if(this._partialBytes > 0) {
|
||||
this._partialOutput.getBytes(this._partialBytes);
|
||||
}
|
||||
|
||||
if(partialBytes > 0 && !finish) {
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
partialBytes - this._partialBytes));
|
||||
this._partialBytes = partialBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
inputLength - this._partialBytes));
|
||||
this._partialBytes = 0;
|
||||
}
|
||||
|
||||
// block complete, increment counter (input block)
|
||||
inc32(this._inBlock);
|
||||
};
|
||||
|
||||
modes.ctr.prototype.decrypt = modes.ctr.prototype.encrypt;
|
||||
|
||||
/** Galois/Counter Mode (GCM) **/
|
||||
|
||||
modes.gcm = function(options) {
|
||||
options = options || {};
|
||||
this.name = 'GCM';
|
||||
this.cipher = options.cipher;
|
||||
this.blockSize = options.blockSize || 16;
|
||||
this._ints = this.blockSize / 4;
|
||||
this._inBlock = new Array(this._ints);
|
||||
this._outBlock = new Array(this._ints);
|
||||
this._partialOutput = forge.util.createBuffer();
|
||||
this._partialBytes = 0;
|
||||
|
||||
// R is actually this value concatenated with 120 more zero bits, but
|
||||
// we only XOR against R so the other zeros have no effect -- we just
|
||||
// apply this value to the first integer in a block
|
||||
this._R = 0xE1000000;
|
||||
};
|
||||
|
||||
modes.gcm.prototype.start = function(options) {
|
||||
if(!('iv' in options)) {
|
||||
throw new Error('Invalid IV parameter.');
|
||||
}
|
||||
// ensure IV is a byte buffer
|
||||
var iv = forge.util.createBuffer(options.iv);
|
||||
|
||||
// no ciphered data processed yet
|
||||
this._cipherLength = 0;
|
||||
|
||||
// default additional data is none
|
||||
var additionalData;
|
||||
if('additionalData' in options) {
|
||||
additionalData = forge.util.createBuffer(options.additionalData);
|
||||
} else {
|
||||
additionalData = forge.util.createBuffer();
|
||||
}
|
||||
|
||||
// default tag length is 128 bits
|
||||
if('tagLength' in options) {
|
||||
this._tagLength = options.tagLength;
|
||||
} else {
|
||||
this._tagLength = 128;
|
||||
}
|
||||
|
||||
// if tag is given, ensure tag matches tag length
|
||||
this._tag = null;
|
||||
if(options.decrypt) {
|
||||
// save tag to check later
|
||||
this._tag = forge.util.createBuffer(options.tag).getBytes();
|
||||
if(this._tag.length !== (this._tagLength / 8)) {
|
||||
throw new Error('Authentication tag does not match tag length.');
|
||||
}
|
||||
}
|
||||
|
||||
// create tmp storage for hash calculation
|
||||
this._hashBlock = new Array(this._ints);
|
||||
|
||||
// no tag generated yet
|
||||
this.tag = null;
|
||||
|
||||
// generate hash subkey
|
||||
// (apply block cipher to "zero" block)
|
||||
this._hashSubkey = new Array(this._ints);
|
||||
this.cipher.encrypt([0, 0, 0, 0], this._hashSubkey);
|
||||
|
||||
// generate table M
|
||||
// use 4-bit tables (32 component decomposition of a 16 byte value)
|
||||
// 8-bit tables take more space and are known to have security
|
||||
// vulnerabilities (in native implementations)
|
||||
this.componentBits = 4;
|
||||
this._m = this.generateHashTable(this._hashSubkey, this.componentBits);
|
||||
|
||||
// Note: support IV length different from 96 bits? (only supporting
|
||||
// 96 bits is recommended by NIST SP-800-38D)
|
||||
// generate J_0
|
||||
var ivLength = iv.length();
|
||||
if(ivLength === 12) {
|
||||
// 96-bit IV
|
||||
this._j0 = [iv.getInt32(), iv.getInt32(), iv.getInt32(), 1];
|
||||
} else {
|
||||
// IV is NOT 96-bits
|
||||
this._j0 = [0, 0, 0, 0];
|
||||
while(iv.length() > 0) {
|
||||
this._j0 = this.ghash(
|
||||
this._hashSubkey, this._j0,
|
||||
[iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]);
|
||||
}
|
||||
this._j0 = this.ghash(
|
||||
this._hashSubkey, this._j0, [0, 0].concat(from64To32(ivLength * 8)));
|
||||
}
|
||||
|
||||
// generate ICB (initial counter block)
|
||||
this._inBlock = this._j0.slice(0);
|
||||
inc32(this._inBlock);
|
||||
this._partialBytes = 0;
|
||||
|
||||
// consume authentication data
|
||||
additionalData = forge.util.createBuffer(additionalData);
|
||||
// save additional data length as a BE 64-bit number
|
||||
this._aDataLength = from64To32(additionalData.length() * 8);
|
||||
// pad additional data to 128 bit (16 byte) block size
|
||||
var overflow = additionalData.length() % this.blockSize;
|
||||
if(overflow) {
|
||||
additionalData.fillWithByte(0, this.blockSize - overflow);
|
||||
}
|
||||
this._s = [0, 0, 0, 0];
|
||||
while(additionalData.length() > 0) {
|
||||
this._s = this.ghash(this._hashSubkey, this._s, [
|
||||
additionalData.getInt32(),
|
||||
additionalData.getInt32(),
|
||||
additionalData.getInt32(),
|
||||
additionalData.getInt32()
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
modes.gcm.prototype.encrypt = function(input, output, finish) {
|
||||
// not enough input to encrypt
|
||||
var inputLength = input.length();
|
||||
if(inputLength === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// handle full block
|
||||
if(this._partialBytes === 0 && inputLength >= this.blockSize) {
|
||||
// XOR input with output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._outBlock[i] ^= input.getInt32());
|
||||
}
|
||||
this._cipherLength += this.blockSize;
|
||||
} else {
|
||||
// handle partial block
|
||||
var partialBytes = (this.blockSize - inputLength) % this.blockSize;
|
||||
if(partialBytes > 0) {
|
||||
partialBytes = this.blockSize - partialBytes;
|
||||
}
|
||||
|
||||
// XOR input with output
|
||||
this._partialOutput.clear();
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
|
||||
}
|
||||
|
||||
if(partialBytes === 0 || finish) {
|
||||
// handle overflow prior to hashing
|
||||
if(finish) {
|
||||
// get block overflow
|
||||
var overflow = inputLength % this.blockSize;
|
||||
this._cipherLength += overflow;
|
||||
// truncate for hash function
|
||||
this._partialOutput.truncate(this.blockSize - overflow);
|
||||
} else {
|
||||
this._cipherLength += this.blockSize;
|
||||
}
|
||||
|
||||
// get output block for hashing
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this._outBlock[i] = this._partialOutput.getInt32();
|
||||
}
|
||||
this._partialOutput.read -= this.blockSize;
|
||||
}
|
||||
|
||||
// skip any previous partial bytes
|
||||
if(this._partialBytes > 0) {
|
||||
this._partialOutput.getBytes(this._partialBytes);
|
||||
}
|
||||
|
||||
if(partialBytes > 0 && !finish) {
|
||||
// block still incomplete, restore input buffer, get partial output,
|
||||
// and return early
|
||||
input.read -= this.blockSize;
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
partialBytes - this._partialBytes));
|
||||
this._partialBytes = partialBytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.putBytes(this._partialOutput.getBytes(
|
||||
inputLength - this._partialBytes));
|
||||
this._partialBytes = 0;
|
||||
}
|
||||
|
||||
// update hash block S
|
||||
this._s = this.ghash(this._hashSubkey, this._s, this._outBlock);
|
||||
|
||||
// increment counter (input block)
|
||||
inc32(this._inBlock);
|
||||
};
|
||||
|
||||
modes.gcm.prototype.decrypt = function(input, output, finish) {
|
||||
// not enough input to decrypt
|
||||
var inputLength = input.length();
|
||||
if(inputLength < this.blockSize && !(finish && inputLength > 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// encrypt block (GCM always uses encryption mode)
|
||||
this.cipher.encrypt(this._inBlock, this._outBlock);
|
||||
|
||||
// increment counter (input block)
|
||||
inc32(this._inBlock);
|
||||
|
||||
// update hash block S
|
||||
this._hashBlock[0] = input.getInt32();
|
||||
this._hashBlock[1] = input.getInt32();
|
||||
this._hashBlock[2] = input.getInt32();
|
||||
this._hashBlock[3] = input.getInt32();
|
||||
this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock);
|
||||
|
||||
// XOR hash input with output
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
output.putInt32(this._outBlock[i] ^ this._hashBlock[i]);
|
||||
}
|
||||
|
||||
// increment cipher data length
|
||||
if(inputLength < this.blockSize) {
|
||||
this._cipherLength += inputLength % this.blockSize;
|
||||
} else {
|
||||
this._cipherLength += this.blockSize;
|
||||
}
|
||||
};
|
||||
|
||||
modes.gcm.prototype.afterFinish = function(output, options) {
|
||||
var rval = true;
|
||||
|
||||
// handle overflow
|
||||
if(options.decrypt && options.overflow) {
|
||||
output.truncate(this.blockSize - options.overflow);
|
||||
}
|
||||
|
||||
// handle authentication tag
|
||||
this.tag = forge.util.createBuffer();
|
||||
|
||||
// concatenate additional data length with cipher length
|
||||
var lengths = this._aDataLength.concat(from64To32(this._cipherLength * 8));
|
||||
|
||||
// include lengths in hash
|
||||
this._s = this.ghash(this._hashSubkey, this._s, lengths);
|
||||
|
||||
// do GCTR(J_0, S)
|
||||
var tag = [];
|
||||
this.cipher.encrypt(this._j0, tag);
|
||||
for(var i = 0; i < this._ints; ++i) {
|
||||
this.tag.putInt32(this._s[i] ^ tag[i]);
|
||||
}
|
||||
|
||||
// trim tag to length
|
||||
this.tag.truncate(this.tag.length() % (this._tagLength / 8));
|
||||
|
||||
// check authentication tag
|
||||
if(options.decrypt && this.tag.bytes() !== this._tag) {
|
||||
rval = false;
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois
|
||||
* field multiplication. The field, GF(2^128), is defined by the polynomial:
|
||||
*
|
||||
* x^128 + x^7 + x^2 + x + 1
|
||||
*
|
||||
* Which is represented in little-endian binary form as: 11100001 (0xe1). When
|
||||
* the value of a coefficient is 1, a bit is set. The value R, is the
|
||||
* concatenation of this value and 120 zero bits, yielding a 128-bit value
|
||||
* which matches the block size.
|
||||
*
|
||||
* This function will multiply two elements (vectors of bytes), X and Y, in
|
||||
* the field GF(2^128). The result is initialized to zero. For each bit of
|
||||
* X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd)
|
||||
* by the current value of Y. For each bit, the value of Y will be raised by
|
||||
* a power of x (multiplied by the polynomial x). This can be achieved by
|
||||
* shifting Y once to the right. If the current value of Y, prior to being
|
||||
* multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial.
|
||||
* Otherwise, we must divide by R after shifting to find the remainder.
|
||||
*
|
||||
* @param x the first block to multiply by the second.
|
||||
* @param y the second block to multiply by the first.
|
||||
*
|
||||
* @return the block result of the multiplication.
|
||||
*/
|
||||
modes.gcm.prototype.multiply = function(x, y) {
|
||||
var z_i = [0, 0, 0, 0];
|
||||
var v_i = y.slice(0);
|
||||
|
||||
// calculate Z_128 (block has 128 bits)
|
||||
for(var i = 0; i < 128; ++i) {
|
||||
// if x_i is 0, Z_{i+1} = Z_i (unchanged)
|
||||
// else Z_{i+1} = Z_i ^ V_i
|
||||
// get x_i by finding 32-bit int position, then left shift 1 by remainder
|
||||
var x_i = x[(i / 32) | 0] & (1 << (31 - i % 32));
|
||||
if(x_i) {
|
||||
z_i[0] ^= v_i[0];
|
||||
z_i[1] ^= v_i[1];
|
||||
z_i[2] ^= v_i[2];
|
||||
z_i[3] ^= v_i[3];
|
||||
}
|
||||
|
||||
// if LSB(V_i) is 1, V_i = V_i >> 1
|
||||
// else V_i = (V_i >> 1) ^ R
|
||||
this.pow(v_i, v_i);
|
||||
}
|
||||
|
||||
return z_i;
|
||||
};
|
||||
|
||||
modes.gcm.prototype.pow = function(x, out) {
|
||||
// if LSB(x) is 1, x = x >>> 1
|
||||
// else x = (x >>> 1) ^ R
|
||||
var lsb = x[3] & 1;
|
||||
|
||||
// always do x >>> 1:
|
||||
// starting with the rightmost integer, shift each integer to the right
|
||||
// one bit, pulling in the bit from the integer to the left as its top
|
||||
// most bit (do this for the last 3 integers)
|
||||
for(var i = 3; i > 0; --i) {
|
||||
out[i] = (x[i] >>> 1) | ((x[i - 1] & 1) << 31);
|
||||
}
|
||||
// shift the first integer normally
|
||||
out[0] = x[0] >>> 1;
|
||||
|
||||
// if lsb was not set, then polynomial had a degree of 127 and doesn't
|
||||
// need to divided; otherwise, XOR with R to find the remainder; we only
|
||||
// need to XOR the first integer since R technically ends w/120 zero bits
|
||||
if(lsb) {
|
||||
out[0] ^= this._R;
|
||||
}
|
||||
};
|
||||
|
||||
modes.gcm.prototype.tableMultiply = function(x) {
|
||||
// assumes 4-bit tables are used
|
||||
var z = [0, 0, 0, 0];
|
||||
for(var i = 0; i < 32; ++i) {
|
||||
var idx = (i / 8) | 0;
|
||||
var x_i = (x[idx] >>> ((7 - (i % 8)) * 4)) & 0xF;
|
||||
var ah = this._m[i][x_i];
|
||||
z[0] ^= ah[0];
|
||||
z[1] ^= ah[1];
|
||||
z[2] ^= ah[2];
|
||||
z[3] ^= ah[3];
|
||||
}
|
||||
return z;
|
||||
};
|
||||
|
||||
/**
|
||||
* A continuing version of the GHASH algorithm that operates on a single
|
||||
* block. The hash block, last hash value (Ym) and the new block to hash
|
||||
* are given.
|
||||
*
|
||||
* @param h the hash block.
|
||||
* @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash.
|
||||
* @param x the block to hash.
|
||||
*
|
||||
* @return the hashed value (Ym).
|
||||
*/
|
||||
modes.gcm.prototype.ghash = function(h, y, x) {
|
||||
y[0] ^= x[0];
|
||||
y[1] ^= x[1];
|
||||
y[2] ^= x[2];
|
||||
y[3] ^= x[3];
|
||||
return this.tableMultiply(y);
|
||||
//return this.multiply(y, h);
|
||||
};
|
||||
|
||||
/**
|
||||
* Precomputes a table for multiplying against the hash subkey. This
|
||||
* mechanism provides a substantial speed increase over multiplication
|
||||
* performed without a table. The table-based multiplication this table is
|
||||
* for solves X * H by multiplying each component of X by H and then
|
||||
* composing the results together using XOR.
|
||||
*
|
||||
* This function can be used to generate tables with different bit sizes
|
||||
* for the components, however, this implementation assumes there are
|
||||
* 32 components of X (which is a 16 byte vector), therefore each component
|
||||
* takes 4-bits (so the table is constructed with bits=4).
|
||||
*
|
||||
* @param h the hash subkey.
|
||||
* @param bits the bit size for a component.
|
||||
*/
|
||||
modes.gcm.prototype.generateHashTable = function(h, bits) {
|
||||
// TODO: There are further optimizations that would use only the
|
||||
// first table M_0 (or some variant) along with a remainder table;
|
||||
// this can be explored in the future
|
||||
var multiplier = 8 / bits;
|
||||
var perInt = 4 * multiplier;
|
||||
var size = 16 * multiplier;
|
||||
var m = new Array(size);
|
||||
for(var i = 0; i < size; ++i) {
|
||||
var tmp = [0, 0, 0, 0];
|
||||
var idx = (i / perInt) | 0;
|
||||
var shft = ((perInt - 1 - (i % perInt)) * bits);
|
||||
tmp[idx] = (1 << (bits - 1)) << shft;
|
||||
m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits);
|
||||
}
|
||||
return m;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a table for multiplying against the hash subkey for one
|
||||
* particular component (out of all possible component values).
|
||||
*
|
||||
* @param mid the pre-multiplied value for the middle key of the table.
|
||||
* @param bits the bit size for a component.
|
||||
*/
|
||||
modes.gcm.prototype.generateSubHashTable = function(mid, bits) {
|
||||
// compute the table quickly by minimizing the number of
|
||||
// POW operations -- they only need to be performed for powers of 2,
|
||||
// all other entries can be composed from those powers using XOR
|
||||
var size = 1 << bits;
|
||||
var half = size >>> 1;
|
||||
var m = new Array(size);
|
||||
m[half] = mid.slice(0);
|
||||
var i = half >>> 1;
|
||||
while(i > 0) {
|
||||
// raise m0[2 * i] and store in m0[i]
|
||||
this.pow(m[2 * i], m[i] = []);
|
||||
i >>= 1;
|
||||
}
|
||||
i = 2;
|
||||
while(i < half) {
|
||||
for(var j = 1; j < i; ++j) {
|
||||
var m_i = m[i];
|
||||
var m_j = m[j];
|
||||
m[i + j] = [
|
||||
m_i[0] ^ m_j[0],
|
||||
m_i[1] ^ m_j[1],
|
||||
m_i[2] ^ m_j[2],
|
||||
m_i[3] ^ m_j[3]
|
||||
];
|
||||
}
|
||||
i *= 2;
|
||||
}
|
||||
m[0] = [0, 0, 0, 0];
|
||||
/* Note: We could avoid storing these by doing composition during multiply
|
||||
calculate top half using composition by speed is preferred. */
|
||||
for(i = half + 1; i < size; ++i) {
|
||||
var c = m[i ^ half];
|
||||
m[i] = [mid[0] ^ c[0], mid[1] ^ c[1], mid[2] ^ c[2], mid[3] ^ c[3]];
|
||||
}
|
||||
return m;
|
||||
};
|
||||
|
||||
/** Utility functions */
|
||||
|
||||
function transformIV(iv) {
|
||||
if(typeof iv === 'string') {
|
||||
// convert iv string into byte buffer
|
||||
iv = forge.util.createBuffer(iv);
|
||||
}
|
||||
|
||||
if(forge.util.isArray(iv) && iv.length > 4) {
|
||||
// convert iv byte array into byte buffer
|
||||
var tmp = iv;
|
||||
iv = forge.util.createBuffer();
|
||||
for(var i = 0; i < tmp.length; ++i) {
|
||||
iv.putByte(tmp[i]);
|
||||
}
|
||||
}
|
||||
if(!forge.util.isArray(iv)) {
|
||||
// convert iv byte buffer into 32-bit integer array
|
||||
iv = [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()];
|
||||
}
|
||||
|
||||
return iv;
|
||||
}
|
||||
|
||||
function inc32(block) {
|
||||
// increment last 32 bits of block only
|
||||
block[block.length - 1] = (block[block.length - 1] + 1) & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
function from64To32(num) {
|
||||
// convert 64-bit number to two BE Int32s
|
||||
return [(num / 0x100000000) | 0, num & 0xFFFFFFFF];
|
||||
}
|
78
node_modules/node-forge/lib/debug.js
generated
vendored
Normal file
78
node_modules/node-forge/lib/debug.js
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Debugging support for web applications.
|
||||
*
|
||||
* @author David I. Lehn <dlehn@digitalbazaar.com>
|
||||
*
|
||||
* Copyright 2008-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
|
||||
/* DEBUG API */
|
||||
module.exports = forge.debug = forge.debug || {};
|
||||
|
||||
// Private storage for debugging.
|
||||
// Useful to expose data that is otherwise unviewable behind closures.
|
||||
// NOTE: remember that this can hold references to data and cause leaks!
|
||||
// format is "forge._debug.<modulename>.<dataname> = data"
|
||||
// Example:
|
||||
// (function() {
|
||||
// var cat = 'forge.test.Test'; // debugging category
|
||||
// var sState = {...}; // local state
|
||||
// forge.debug.set(cat, 'sState', sState);
|
||||
// })();
|
||||
forge.debug.storage = {};
|
||||
|
||||
/**
|
||||
* Gets debug data. Omit name for all cat data Omit name and cat for
|
||||
* all data.
|
||||
*
|
||||
* @param cat name of debugging category.
|
||||
* @param name name of data to get (optional).
|
||||
* @return object with requested debug data or undefined.
|
||||
*/
|
||||
forge.debug.get = function(cat, name) {
|
||||
var rval;
|
||||
if(typeof(cat) === 'undefined') {
|
||||
rval = forge.debug.storage;
|
||||
} else if(cat in forge.debug.storage) {
|
||||
if(typeof(name) === 'undefined') {
|
||||
rval = forge.debug.storage[cat];
|
||||
} else {
|
||||
rval = forge.debug.storage[cat][name];
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets debug data.
|
||||
*
|
||||
* @param cat name of debugging category.
|
||||
* @param name name of data to set.
|
||||
* @param data data to set.
|
||||
*/
|
||||
forge.debug.set = function(cat, name, data) {
|
||||
if(!(cat in forge.debug.storage)) {
|
||||
forge.debug.storage[cat] = {};
|
||||
}
|
||||
forge.debug.storage[cat][name] = data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears debug data. Omit name for all cat data. Omit name and cat for
|
||||
* all data.
|
||||
*
|
||||
* @param cat name of debugging category.
|
||||
* @param name name of data to clear or omit to clear entire category.
|
||||
*/
|
||||
forge.debug.clear = function(cat, name) {
|
||||
if(typeof(cat) === 'undefined') {
|
||||
forge.debug.storage = {};
|
||||
} else if(cat in forge.debug.storage) {
|
||||
if(typeof(name) === 'undefined') {
|
||||
delete forge.debug.storage[cat];
|
||||
} else {
|
||||
delete forge.debug.storage[cat][name];
|
||||
}
|
||||
}
|
||||
};
|
495
node_modules/node-forge/lib/des.js
generated
vendored
Normal file
495
node_modules/node-forge/lib/des.js
generated
vendored
Normal file
@ -0,0 +1,495 @@
|
||||
/**
|
||||
* DES (Data Encryption Standard) implementation.
|
||||
*
|
||||
* This implementation supports DES as well as 3DES-EDE in ECB and CBC mode.
|
||||
* It is based on the BSD-licensed implementation by Paul Tero:
|
||||
*
|
||||
* Paul Tero, July 2001
|
||||
* http://www.tero.co.uk/des/
|
||||
*
|
||||
* Optimised for performance with large blocks by Michael Hayworth, November 2001
|
||||
* http://www.netdealing.com
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @author Stefan Siegl
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
* Copyright (c) 2012-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./cipher');
|
||||
require('./cipherModes');
|
||||
require('./util');
|
||||
|
||||
/* DES API */
|
||||
module.exports = forge.des = forge.des || {};
|
||||
|
||||
/**
|
||||
* Deprecated. Instead, use:
|
||||
*
|
||||
* var cipher = forge.cipher.createCipher('DES-<mode>', key);
|
||||
* cipher.start({iv: iv});
|
||||
*
|
||||
* Creates an DES cipher object to encrypt data using the given symmetric key.
|
||||
* The output will be stored in the 'output' member of the returned cipher.
|
||||
*
|
||||
* The key and iv may be given as binary-encoded strings of bytes or
|
||||
* byte buffers.
|
||||
*
|
||||
* @param key the symmetric key to use (64 or 192 bits).
|
||||
* @param iv the initialization vector to use.
|
||||
* @param output the buffer to write to, null to create one.
|
||||
* @param mode the cipher mode to use (default: 'CBC' if IV is
|
||||
* given, 'ECB' if null).
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.des.startEncrypting = function(key, iv, output, mode) {
|
||||
var cipher = _createCipher({
|
||||
key: key,
|
||||
output: output,
|
||||
decrypt: false,
|
||||
mode: mode || (iv === null ? 'ECB' : 'CBC')
|
||||
});
|
||||
cipher.start(iv);
|
||||
return cipher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated. Instead, use:
|
||||
*
|
||||
* var cipher = forge.cipher.createCipher('DES-<mode>', key);
|
||||
*
|
||||
* Creates an DES cipher object to encrypt data using the given symmetric key.
|
||||
*
|
||||
* The key may be given as a binary-encoded string of bytes or a byte buffer.
|
||||
*
|
||||
* @param key the symmetric key to use (64 or 192 bits).
|
||||
* @param mode the cipher mode to use (default: 'CBC').
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.des.createEncryptionCipher = function(key, mode) {
|
||||
return _createCipher({
|
||||
key: key,
|
||||
output: null,
|
||||
decrypt: false,
|
||||
mode: mode
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated. Instead, use:
|
||||
*
|
||||
* var decipher = forge.cipher.createDecipher('DES-<mode>', key);
|
||||
* decipher.start({iv: iv});
|
||||
*
|
||||
* Creates an DES cipher object to decrypt data using the given symmetric key.
|
||||
* The output will be stored in the 'output' member of the returned cipher.
|
||||
*
|
||||
* The key and iv may be given as binary-encoded strings of bytes or
|
||||
* byte buffers.
|
||||
*
|
||||
* @param key the symmetric key to use (64 or 192 bits).
|
||||
* @param iv the initialization vector to use.
|
||||
* @param output the buffer to write to, null to create one.
|
||||
* @param mode the cipher mode to use (default: 'CBC' if IV is
|
||||
* given, 'ECB' if null).
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.des.startDecrypting = function(key, iv, output, mode) {
|
||||
var cipher = _createCipher({
|
||||
key: key,
|
||||
output: output,
|
||||
decrypt: true,
|
||||
mode: mode || (iv === null ? 'ECB' : 'CBC')
|
||||
});
|
||||
cipher.start(iv);
|
||||
return cipher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deprecated. Instead, use:
|
||||
*
|
||||
* var decipher = forge.cipher.createDecipher('DES-<mode>', key);
|
||||
*
|
||||
* Creates an DES cipher object to decrypt data using the given symmetric key.
|
||||
*
|
||||
* The key may be given as a binary-encoded string of bytes or a byte buffer.
|
||||
*
|
||||
* @param key the symmetric key to use (64 or 192 bits).
|
||||
* @param mode the cipher mode to use (default: 'CBC').
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.des.createDecryptionCipher = function(key, mode) {
|
||||
return _createCipher({
|
||||
key: key,
|
||||
output: null,
|
||||
decrypt: true,
|
||||
mode: mode
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new DES cipher algorithm object.
|
||||
*
|
||||
* @param name the name of the algorithm.
|
||||
* @param mode the mode factory function.
|
||||
*
|
||||
* @return the DES algorithm object.
|
||||
*/
|
||||
forge.des.Algorithm = function(name, mode) {
|
||||
var self = this;
|
||||
self.name = name;
|
||||
self.mode = new mode({
|
||||
blockSize: 8,
|
||||
cipher: {
|
||||
encrypt: function(inBlock, outBlock) {
|
||||
return _updateBlock(self._keys, inBlock, outBlock, false);
|
||||
},
|
||||
decrypt: function(inBlock, outBlock) {
|
||||
return _updateBlock(self._keys, inBlock, outBlock, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
self._init = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes this DES algorithm by expanding its key.
|
||||
*
|
||||
* @param options the options to use.
|
||||
* key the key to use with this algorithm.
|
||||
* decrypt true if the algorithm should be initialized for decryption,
|
||||
* false for encryption.
|
||||
*/
|
||||
forge.des.Algorithm.prototype.initialize = function(options) {
|
||||
if(this._init) {
|
||||
return;
|
||||
}
|
||||
|
||||
var key = forge.util.createBuffer(options.key);
|
||||
if(this.name.indexOf('3DES') === 0) {
|
||||
if(key.length() !== 24) {
|
||||
throw new Error('Invalid Triple-DES key size: ' + key.length() * 8);
|
||||
}
|
||||
}
|
||||
|
||||
// do key expansion to 16 or 48 subkeys (single or triple DES)
|
||||
this._keys = _createKeys(key);
|
||||
this._init = true;
|
||||
};
|
||||
|
||||
/** Register DES algorithms **/
|
||||
|
||||
registerAlgorithm('DES-ECB', forge.cipher.modes.ecb);
|
||||
registerAlgorithm('DES-CBC', forge.cipher.modes.cbc);
|
||||
registerAlgorithm('DES-CFB', forge.cipher.modes.cfb);
|
||||
registerAlgorithm('DES-OFB', forge.cipher.modes.ofb);
|
||||
registerAlgorithm('DES-CTR', forge.cipher.modes.ctr);
|
||||
|
||||
registerAlgorithm('3DES-ECB', forge.cipher.modes.ecb);
|
||||
registerAlgorithm('3DES-CBC', forge.cipher.modes.cbc);
|
||||
registerAlgorithm('3DES-CFB', forge.cipher.modes.cfb);
|
||||
registerAlgorithm('3DES-OFB', forge.cipher.modes.ofb);
|
||||
registerAlgorithm('3DES-CTR', forge.cipher.modes.ctr);
|
||||
|
||||
function registerAlgorithm(name, mode) {
|
||||
var factory = function() {
|
||||
return new forge.des.Algorithm(name, mode);
|
||||
};
|
||||
forge.cipher.registerAlgorithm(name, factory);
|
||||
}
|
||||
|
||||
/** DES implementation **/
|
||||
|
||||
var spfunction1 = [0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004];
|
||||
var spfunction2 = [-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000];
|
||||
var spfunction3 = [0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200];
|
||||
var spfunction4 = [0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080];
|
||||
var spfunction5 = [0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100];
|
||||
var spfunction6 = [0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010];
|
||||
var spfunction7 = [0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002];
|
||||
var spfunction8 = [0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000];
|
||||
|
||||
/**
|
||||
* Create necessary sub keys.
|
||||
*
|
||||
* @param key the 64-bit or 192-bit key.
|
||||
*
|
||||
* @return the expanded keys.
|
||||
*/
|
||||
function _createKeys(key) {
|
||||
var pc2bytes0 = [0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204],
|
||||
pc2bytes1 = [0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101],
|
||||
pc2bytes2 = [0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808],
|
||||
pc2bytes3 = [0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000],
|
||||
pc2bytes4 = [0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010],
|
||||
pc2bytes5 = [0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420],
|
||||
pc2bytes6 = [0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002],
|
||||
pc2bytes7 = [0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800],
|
||||
pc2bytes8 = [0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002],
|
||||
pc2bytes9 = [0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408],
|
||||
pc2bytes10 = [0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020],
|
||||
pc2bytes11 = [0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200],
|
||||
pc2bytes12 = [0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010],
|
||||
pc2bytes13 = [0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105];
|
||||
|
||||
// how many iterations (1 for des, 3 for triple des)
|
||||
// changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
|
||||
var iterations = key.length() > 8 ? 3 : 1;
|
||||
|
||||
// stores the return keys
|
||||
var keys = [];
|
||||
|
||||
// now define the left shifts which need to be done
|
||||
var shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0];
|
||||
|
||||
var n = 0, tmp;
|
||||
for(var j = 0; j < iterations; j++) {
|
||||
var left = key.getInt32();
|
||||
var right = key.getInt32();
|
||||
|
||||
tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 4);
|
||||
|
||||
tmp = ((right >>> -16) ^ left) & 0x0000ffff;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << -16);
|
||||
|
||||
tmp = ((left >>> 2) ^ right) & 0x33333333;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 2);
|
||||
|
||||
tmp = ((right >>> -16) ^ left) & 0x0000ffff;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << -16);
|
||||
|
||||
tmp = ((left >>> 1) ^ right) & 0x55555555;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 1);
|
||||
|
||||
tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << 8);
|
||||
|
||||
tmp = ((left >>> 1) ^ right) & 0x55555555;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 1);
|
||||
|
||||
// right needs to be shifted and OR'd with last four bits of left
|
||||
tmp = (left << 8) | ((right >>> 20) & 0x000000f0);
|
||||
|
||||
// left needs to be put upside down
|
||||
left = ((right << 24) | ((right << 8) & 0xff0000) |
|
||||
((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0));
|
||||
right = tmp;
|
||||
|
||||
// now go through and perform these shifts on the left and right keys
|
||||
for(var i = 0; i < shifts.length; ++i) {
|
||||
//shift the keys either one or two bits to the left
|
||||
if(shifts[i]) {
|
||||
left = (left << 2) | (left >>> 26);
|
||||
right = (right << 2) | (right >>> 26);
|
||||
} else {
|
||||
left = (left << 1) | (left >>> 27);
|
||||
right = (right << 1) | (right >>> 27);
|
||||
}
|
||||
left &= -0xf;
|
||||
right &= -0xf;
|
||||
|
||||
// now apply PC-2, in such a way that E is easier when encrypting or
|
||||
// decrypting this conversion will look like PC-2 except only the last 6
|
||||
// bits of each byte are used rather than 48 consecutive bits and the
|
||||
// order of lines will be according to how the S selection functions will
|
||||
// be applied: S2, S4, S6, S8, S1, S3, S5, S7
|
||||
var lefttmp = (
|
||||
pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] |
|
||||
pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] |
|
||||
pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] |
|
||||
pc2bytes6[(left >>> 4) & 0xf]);
|
||||
var righttmp = (
|
||||
pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] |
|
||||
pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] |
|
||||
pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] |
|
||||
pc2bytes13[(right >>> 4) & 0xf]);
|
||||
tmp = ((righttmp >>> 16) ^ lefttmp) & 0x0000ffff;
|
||||
keys[n++] = lefttmp ^ tmp;
|
||||
keys[n++] = righttmp ^ (tmp << 16);
|
||||
}
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a single block (1 byte) using DES. The update will either
|
||||
* encrypt or decrypt the block.
|
||||
*
|
||||
* @param keys the expanded keys.
|
||||
* @param input the input block (an array of 32-bit words).
|
||||
* @param output the updated output block.
|
||||
* @param decrypt true to decrypt the block, false to encrypt it.
|
||||
*/
|
||||
function _updateBlock(keys, input, output, decrypt) {
|
||||
// set up loops for single or triple DES
|
||||
var iterations = keys.length === 32 ? 3 : 9;
|
||||
var looping;
|
||||
if(iterations === 3) {
|
||||
looping = decrypt ? [30, -2, -2] : [0, 32, 2];
|
||||
} else {
|
||||
looping = (decrypt ?
|
||||
[94, 62, -2, 32, 64, 2, 30, -2, -2] :
|
||||
[0, 32, 2, 62, 30, -2, 64, 96, 2]);
|
||||
}
|
||||
|
||||
var tmp;
|
||||
|
||||
var left = input[0];
|
||||
var right = input[1];
|
||||
|
||||
// first each 64 bit chunk of the message must be permuted according to IP
|
||||
tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 4);
|
||||
|
||||
tmp = ((left >>> 16) ^ right) & 0x0000ffff;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 16);
|
||||
|
||||
tmp = ((right >>> 2) ^ left) & 0x33333333;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << 2);
|
||||
|
||||
tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << 8);
|
||||
|
||||
tmp = ((left >>> 1) ^ right) & 0x55555555;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 1);
|
||||
|
||||
// rotate left 1 bit
|
||||
left = ((left << 1) | (left >>> 31));
|
||||
right = ((right << 1) | (right >>> 31));
|
||||
|
||||
for(var j = 0; j < iterations; j += 3) {
|
||||
var endloop = looping[j + 1];
|
||||
var loopinc = looping[j + 2];
|
||||
|
||||
// now go through and perform the encryption or decryption
|
||||
for(var i = looping[j]; i != endloop; i += loopinc) {
|
||||
var right1 = right ^ keys[i];
|
||||
var right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1];
|
||||
|
||||
// passing these bytes through the S selection functions
|
||||
tmp = left;
|
||||
left = right;
|
||||
right = tmp ^ (
|
||||
spfunction2[(right1 >>> 24) & 0x3f] |
|
||||
spfunction4[(right1 >>> 16) & 0x3f] |
|
||||
spfunction6[(right1 >>> 8) & 0x3f] |
|
||||
spfunction8[right1 & 0x3f] |
|
||||
spfunction1[(right2 >>> 24) & 0x3f] |
|
||||
spfunction3[(right2 >>> 16) & 0x3f] |
|
||||
spfunction5[(right2 >>> 8) & 0x3f] |
|
||||
spfunction7[right2 & 0x3f]);
|
||||
}
|
||||
// unreverse left and right
|
||||
tmp = left;
|
||||
left = right;
|
||||
right = tmp;
|
||||
}
|
||||
|
||||
// rotate right 1 bit
|
||||
left = ((left >>> 1) | (left << 31));
|
||||
right = ((right >>> 1) | (right << 31));
|
||||
|
||||
// now perform IP-1, which is IP in the opposite direction
|
||||
tmp = ((left >>> 1) ^ right) & 0x55555555;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 1);
|
||||
|
||||
tmp = ((right >>> 8) ^ left) & 0x00ff00ff;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << 8);
|
||||
|
||||
tmp = ((right >>> 2) ^ left) & 0x33333333;
|
||||
left ^= tmp;
|
||||
right ^= (tmp << 2);
|
||||
|
||||
tmp = ((left >>> 16) ^ right) & 0x0000ffff;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 16);
|
||||
|
||||
tmp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
|
||||
right ^= tmp;
|
||||
left ^= (tmp << 4);
|
||||
|
||||
output[0] = left;
|
||||
output[1] = right;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated. Instead, use:
|
||||
*
|
||||
* forge.cipher.createCipher('DES-<mode>', key);
|
||||
* forge.cipher.createDecipher('DES-<mode>', key);
|
||||
*
|
||||
* Creates a deprecated DES cipher object. This object's mode will default to
|
||||
* CBC (cipher-block-chaining).
|
||||
*
|
||||
* The key may be given as a binary-encoded string of bytes or a byte buffer.
|
||||
*
|
||||
* @param options the options to use.
|
||||
* key the symmetric key to use (64 or 192 bits).
|
||||
* output the buffer to write to.
|
||||
* decrypt true for decryption, false for encryption.
|
||||
* mode the cipher mode to use (default: 'CBC').
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
function _createCipher(options) {
|
||||
options = options || {};
|
||||
var mode = (options.mode || 'CBC').toUpperCase();
|
||||
var algorithm = 'DES-' + mode;
|
||||
|
||||
var cipher;
|
||||
if(options.decrypt) {
|
||||
cipher = forge.cipher.createDecipher(algorithm, options.key);
|
||||
} else {
|
||||
cipher = forge.cipher.createCipher(algorithm, options.key);
|
||||
}
|
||||
|
||||
// backwards compatible start API
|
||||
var start = cipher.start;
|
||||
cipher.start = function(iv, options) {
|
||||
// backwards compatibility: support second arg as output buffer
|
||||
var output = null;
|
||||
if(options instanceof forge.util.ByteBuffer) {
|
||||
output = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
options.output = output;
|
||||
options.iv = iv;
|
||||
start.call(cipher, options);
|
||||
};
|
||||
|
||||
return cipher;
|
||||
}
|
996
node_modules/node-forge/lib/ed25519.js
generated
vendored
Normal file
996
node_modules/node-forge/lib/ed25519.js
generated
vendored
Normal file
@ -0,0 +1,996 @@
|
||||
/**
|
||||
* JavaScript implementation of Ed25519.
|
||||
*
|
||||
* Copyright (c) 2017-2018 Digital Bazaar, Inc.
|
||||
*
|
||||
* This implementation is based on the most excellent TweetNaCl which is
|
||||
* in the public domain. Many thanks to its contributors:
|
||||
*
|
||||
* https://github.com/dchest/tweetnacl-js
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./jsbn');
|
||||
require('./random');
|
||||
require('./sha512');
|
||||
require('./util');
|
||||
|
||||
if(typeof BigInteger === 'undefined') {
|
||||
var BigInteger = forge.jsbn.BigInteger;
|
||||
}
|
||||
|
||||
var ByteBuffer = forge.util.ByteBuffer;
|
||||
var NativeBuffer = typeof Buffer === 'undefined' ? Uint8Array : Buffer;
|
||||
|
||||
/*
|
||||
* Ed25519 algorithms, see RFC 8032:
|
||||
* https://tools.ietf.org/html/rfc8032
|
||||
*/
|
||||
forge.pki = forge.pki || {};
|
||||
module.exports = forge.pki.ed25519 = forge.ed25519 = forge.ed25519 || {};
|
||||
var ed25519 = forge.ed25519;
|
||||
|
||||
ed25519.constants = {};
|
||||
ed25519.constants.PUBLIC_KEY_BYTE_LENGTH = 32;
|
||||
ed25519.constants.PRIVATE_KEY_BYTE_LENGTH = 64;
|
||||
ed25519.constants.SEED_BYTE_LENGTH = 32;
|
||||
ed25519.constants.SIGN_BYTE_LENGTH = 64;
|
||||
ed25519.constants.HASH_BYTE_LENGTH = 64;
|
||||
|
||||
ed25519.generateKeyPair = function(options) {
|
||||
options = options || {};
|
||||
var seed = options.seed;
|
||||
if(seed === undefined) {
|
||||
// generate seed
|
||||
seed = forge.random.getBytesSync(ed25519.constants.SEED_BYTE_LENGTH);
|
||||
} else if(typeof seed === 'string') {
|
||||
if(seed.length !== ed25519.constants.SEED_BYTE_LENGTH) {
|
||||
throw new TypeError(
|
||||
'"seed" must be ' + ed25519.constants.SEED_BYTE_LENGTH +
|
||||
' bytes in length.');
|
||||
}
|
||||
} else if(!(seed instanceof Uint8Array)) {
|
||||
throw new TypeError(
|
||||
'"seed" must be a node.js Buffer, Uint8Array, or a binary string.');
|
||||
}
|
||||
|
||||
seed = messageToNativeBuffer({message: seed, encoding: 'binary'});
|
||||
|
||||
var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
|
||||
var sk = new NativeBuffer(ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
|
||||
for(var i = 0; i < 32; ++i) {
|
||||
sk[i] = seed[i];
|
||||
}
|
||||
crypto_sign_keypair(pk, sk);
|
||||
return {publicKey: pk, privateKey: sk};
|
||||
};
|
||||
|
||||
ed25519.publicKeyFromPrivateKey = function(options) {
|
||||
options = options || {};
|
||||
var privateKey = messageToNativeBuffer({
|
||||
message: options.privateKey, encoding: 'binary'
|
||||
});
|
||||
if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
|
||||
throw new TypeError(
|
||||
'"options.privateKey" must have a byte length of ' +
|
||||
ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
|
||||
}
|
||||
|
||||
var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
|
||||
for(var i = 0; i < pk.length; ++i) {
|
||||
pk[i] = privateKey[32 + i];
|
||||
}
|
||||
return pk;
|
||||
};
|
||||
|
||||
ed25519.sign = function(options) {
|
||||
options = options || {};
|
||||
var msg = messageToNativeBuffer(options);
|
||||
var privateKey = messageToNativeBuffer({
|
||||
message: options.privateKey,
|
||||
encoding: 'binary'
|
||||
});
|
||||
if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
|
||||
throw new TypeError(
|
||||
'"options.privateKey" must have a byte length of ' +
|
||||
ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
|
||||
}
|
||||
|
||||
var signedMsg = new NativeBuffer(
|
||||
ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
|
||||
crypto_sign(signedMsg, msg, msg.length, privateKey);
|
||||
|
||||
var sig = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH);
|
||||
for(var i = 0; i < sig.length; ++i) {
|
||||
sig[i] = signedMsg[i];
|
||||
}
|
||||
return sig;
|
||||
};
|
||||
|
||||
ed25519.verify = function(options) {
|
||||
options = options || {};
|
||||
var msg = messageToNativeBuffer(options);
|
||||
if(options.signature === undefined) {
|
||||
throw new TypeError(
|
||||
'"options.signature" must be a node.js Buffer, a Uint8Array, a forge ' +
|
||||
'ByteBuffer, or a binary string.');
|
||||
}
|
||||
var sig = messageToNativeBuffer({
|
||||
message: options.signature,
|
||||
encoding: 'binary'
|
||||
});
|
||||
if(sig.length !== ed25519.constants.SIGN_BYTE_LENGTH) {
|
||||
throw new TypeError(
|
||||
'"options.signature" must have a byte length of ' +
|
||||
ed25519.constants.SIGN_BYTE_LENGTH);
|
||||
}
|
||||
var publicKey = messageToNativeBuffer({
|
||||
message: options.publicKey,
|
||||
encoding: 'binary'
|
||||
});
|
||||
if(publicKey.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) {
|
||||
throw new TypeError(
|
||||
'"options.publicKey" must have a byte length of ' +
|
||||
ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
|
||||
}
|
||||
|
||||
var sm = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
|
||||
var m = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
|
||||
var i;
|
||||
for(i = 0; i < ed25519.constants.SIGN_BYTE_LENGTH; ++i) {
|
||||
sm[i] = sig[i];
|
||||
}
|
||||
for(i = 0; i < msg.length; ++i) {
|
||||
sm[i + ed25519.constants.SIGN_BYTE_LENGTH] = msg[i];
|
||||
}
|
||||
return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0);
|
||||
};
|
||||
|
||||
function messageToNativeBuffer(options) {
|
||||
var message = options.message;
|
||||
if(message instanceof Uint8Array) {
|
||||
return message;
|
||||
}
|
||||
|
||||
var encoding = options.encoding;
|
||||
if(message === undefined) {
|
||||
if(options.md) {
|
||||
// TODO: more rigorous validation that `md` is a MessageDigest
|
||||
message = options.md.digest().getBytes();
|
||||
encoding = 'binary';
|
||||
} else {
|
||||
throw new TypeError('"options.message" or "options.md" not specified.');
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof message === 'string' && !encoding) {
|
||||
throw new TypeError('"options.encoding" must be "binary" or "utf8".');
|
||||
}
|
||||
|
||||
if(typeof message === 'string') {
|
||||
if(typeof Buffer !== 'undefined') {
|
||||
return new Buffer(message, encoding);
|
||||
}
|
||||
message = new ByteBuffer(message, encoding);
|
||||
} else if(!(message instanceof ByteBuffer)) {
|
||||
throw new TypeError(
|
||||
'"options.message" must be a node.js Buffer, a Uint8Array, a forge ' +
|
||||
'ByteBuffer, or a string with "options.encoding" specifying its ' +
|
||||
'encoding.');
|
||||
}
|
||||
|
||||
// convert to native buffer
|
||||
var buffer = new NativeBuffer(message.length());
|
||||
for(var i = 0; i < buffer.length; ++i) {
|
||||
buffer[i] = message.at(i);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
var gf0 = gf();
|
||||
var gf1 = gf([1]);
|
||||
var D = gf([
|
||||
0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070,
|
||||
0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]);
|
||||
var D2 = gf([
|
||||
0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0,
|
||||
0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]);
|
||||
var X = gf([
|
||||
0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c,
|
||||
0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]);
|
||||
var Y = gf([
|
||||
0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
|
||||
0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]);
|
||||
var L = new Float64Array([
|
||||
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
|
||||
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
|
||||
var I = gf([
|
||||
0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43,
|
||||
0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
|
||||
|
||||
// TODO: update forge buffer implementation to use `Buffer` or `Uint8Array`,
|
||||
// whichever is available, to improve performance
|
||||
function sha512(msg, msgLen) {
|
||||
// Note: `out` and `msg` are NativeBuffer
|
||||
var md = forge.md.sha512.create();
|
||||
var buffer = new ByteBuffer(msg);
|
||||
md.update(buffer.getBytes(msgLen), 'binary');
|
||||
const hash = md.digest().getBytes();
|
||||
if(typeof Buffer !== 'undefined') {
|
||||
return new Buffer(hash, 'binary');
|
||||
}
|
||||
var out = new NativeBuffer(ed25519.constants.HASH_BYTE_LENGTH);
|
||||
for(var i = 0; i < 64; ++i) {
|
||||
out[i] = hash.charCodeAt(i);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function crypto_sign_keypair(pk, sk) {
|
||||
var p = [gf(), gf(), gf(), gf()];
|
||||
var i;
|
||||
|
||||
var d = sha512(sk, 32);
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
|
||||
scalarbase(p, d);
|
||||
pack(pk, p);
|
||||
|
||||
for(i = 0; i < 32; ++i) {
|
||||
sk[i + 32] = pk[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: difference from C - smlen returned, not passed as argument.
|
||||
function crypto_sign(sm, m, n, sk) {
|
||||
var i, j, x = new Float64Array(64);
|
||||
var p = [gf(), gf(), gf(), gf()];
|
||||
|
||||
var d = sha512(sk, 32);
|
||||
d[0] &= 248;
|
||||
d[31] &= 127;
|
||||
d[31] |= 64;
|
||||
|
||||
var smlen = n + 64;
|
||||
for(i = 0; i < n; ++i) {
|
||||
sm[64 + i] = m[i];
|
||||
}
|
||||
for(i = 0; i < 32; ++i) {
|
||||
sm[32 + i] = d[32 + i];
|
||||
}
|
||||
|
||||
var r = sha512(sm.subarray(32), n + 32);
|
||||
reduce(r);
|
||||
scalarbase(p, r);
|
||||
pack(sm, p);
|
||||
|
||||
for(i = 32; i < 64; ++i) {
|
||||
sm[i] = sk[i];
|
||||
}
|
||||
var h = sha512(sm, n + 64);
|
||||
reduce(h);
|
||||
|
||||
for(i = 32; i < 64; ++i) {
|
||||
x[i] = 0;
|
||||
}
|
||||
for(i = 0; i < 32; ++i) {
|
||||
x[i] = r[i];
|
||||
}
|
||||
for(i = 0; i < 32; ++i) {
|
||||
for(j = 0; j < 32; j++) {
|
||||
x[i + j] += h[i] * d[j];
|
||||
}
|
||||
}
|
||||
|
||||
modL(sm.subarray(32), x);
|
||||
return smlen;
|
||||
}
|
||||
|
||||
function crypto_sign_open(m, sm, n, pk) {
|
||||
var i, mlen;
|
||||
var t = new NativeBuffer(32);
|
||||
var p = [gf(), gf(), gf(), gf()],
|
||||
q = [gf(), gf(), gf(), gf()];
|
||||
|
||||
mlen = -1;
|
||||
if(n < 64) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(unpackneg(q, pk)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
m[i] = sm[i];
|
||||
}
|
||||
for(i = 0; i < 32; ++i) {
|
||||
m[i + 32] = pk[i];
|
||||
}
|
||||
var h = sha512(m, n);
|
||||
reduce(h);
|
||||
scalarmult(p, q, h);
|
||||
|
||||
scalarbase(q, sm.subarray(32));
|
||||
add(p, q);
|
||||
pack(t, p);
|
||||
|
||||
n -= 64;
|
||||
if(crypto_verify_32(sm, 0, t, 0)) {
|
||||
for(i = 0; i < n; ++i) {
|
||||
m[i] = 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < n; ++i) {
|
||||
m[i] = sm[i + 64];
|
||||
}
|
||||
mlen = n;
|
||||
return mlen;
|
||||
}
|
||||
|
||||
function modL(r, x) {
|
||||
var carry, i, j, k;
|
||||
for(i = 63; i >= 32; --i) {
|
||||
carry = 0;
|
||||
for(j = i - 32, k = i - 12; j < k; ++j) {
|
||||
x[j] += carry - 16 * x[i] * L[j - (i - 32)];
|
||||
carry = (x[j] + 128) >> 8;
|
||||
x[j] -= carry * 256;
|
||||
}
|
||||
x[j] += carry;
|
||||
x[i] = 0;
|
||||
}
|
||||
carry = 0;
|
||||
for(j = 0; j < 32; ++j) {
|
||||
x[j] += carry - (x[31] >> 4) * L[j];
|
||||
carry = x[j] >> 8;
|
||||
x[j] &= 255;
|
||||
}
|
||||
for(j = 0; j < 32; ++j) {
|
||||
x[j] -= carry * L[j];
|
||||
}
|
||||
for(i = 0; i < 32; ++i) {
|
||||
x[i + 1] += x[i] >> 8;
|
||||
r[i] = x[i] & 255;
|
||||
}
|
||||
}
|
||||
|
||||
function reduce(r) {
|
||||
var x = new Float64Array(64);
|
||||
for(var i = 0; i < 64; ++i) {
|
||||
x[i] = r[i];
|
||||
r[i] = 0;
|
||||
}
|
||||
modL(r, x);
|
||||
}
|
||||
|
||||
function add(p, q) {
|
||||
var a = gf(), b = gf(), c = gf(),
|
||||
d = gf(), e = gf(), f = gf(),
|
||||
g = gf(), h = gf(), t = gf();
|
||||
|
||||
Z(a, p[1], p[0]);
|
||||
Z(t, q[1], q[0]);
|
||||
M(a, a, t);
|
||||
A(b, p[0], p[1]);
|
||||
A(t, q[0], q[1]);
|
||||
M(b, b, t);
|
||||
M(c, p[3], q[3]);
|
||||
M(c, c, D2);
|
||||
M(d, p[2], q[2]);
|
||||
A(d, d, d);
|
||||
Z(e, b, a);
|
||||
Z(f, d, c);
|
||||
A(g, d, c);
|
||||
A(h, b, a);
|
||||
|
||||
M(p[0], e, f);
|
||||
M(p[1], h, g);
|
||||
M(p[2], g, f);
|
||||
M(p[3], e, h);
|
||||
}
|
||||
|
||||
function cswap(p, q, b) {
|
||||
for(var i = 0; i < 4; ++i) {
|
||||
sel25519(p[i], q[i], b);
|
||||
}
|
||||
}
|
||||
|
||||
function pack(r, p) {
|
||||
var tx = gf(), ty = gf(), zi = gf();
|
||||
inv25519(zi, p[2]);
|
||||
M(tx, p[0], zi);
|
||||
M(ty, p[1], zi);
|
||||
pack25519(r, ty);
|
||||
r[31] ^= par25519(tx) << 7;
|
||||
}
|
||||
|
||||
function pack25519(o, n) {
|
||||
var i, j, b;
|
||||
var m = gf(), t = gf();
|
||||
for(i = 0; i < 16; ++i) {
|
||||
t[i] = n[i];
|
||||
}
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
car25519(t);
|
||||
for(j = 0; j < 2; ++j) {
|
||||
m[0] = t[0] - 0xffed;
|
||||
for(i = 1; i < 15; ++i) {
|
||||
m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
|
||||
m[i-1] &= 0xffff;
|
||||
}
|
||||
m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
|
||||
b = (m[15] >> 16) & 1;
|
||||
m[14] &= 0xffff;
|
||||
sel25519(t, m, 1 - b);
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
o[2 * i] = t[i] & 0xff;
|
||||
o[2 * i + 1] = t[i] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
function unpackneg(r, p) {
|
||||
var t = gf(), chk = gf(), num = gf(),
|
||||
den = gf(), den2 = gf(), den4 = gf(),
|
||||
den6 = gf();
|
||||
|
||||
set25519(r[2], gf1);
|
||||
unpack25519(r[1], p);
|
||||
S(num, r[1]);
|
||||
M(den, num, D);
|
||||
Z(num, num, r[2]);
|
||||
A(den, r[2], den);
|
||||
|
||||
S(den2, den);
|
||||
S(den4, den2);
|
||||
M(den6, den4, den2);
|
||||
M(t, den6, num);
|
||||
M(t, t, den);
|
||||
|
||||
pow2523(t, t);
|
||||
M(t, t, num);
|
||||
M(t, t, den);
|
||||
M(t, t, den);
|
||||
M(r[0], t, den);
|
||||
|
||||
S(chk, r[0]);
|
||||
M(chk, chk, den);
|
||||
if(neq25519(chk, num)) {
|
||||
M(r[0], r[0], I);
|
||||
}
|
||||
|
||||
S(chk, r[0]);
|
||||
M(chk, chk, den);
|
||||
if(neq25519(chk, num)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(par25519(r[0]) === (p[31] >> 7)) {
|
||||
Z(r[0], gf0, r[0]);
|
||||
}
|
||||
|
||||
M(r[3], r[0], r[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
function unpack25519(o, n) {
|
||||
var i;
|
||||
for(i = 0; i < 16; ++i) {
|
||||
o[i] = n[2 * i] + (n[2 * i + 1] << 8);
|
||||
}
|
||||
o[15] &= 0x7fff;
|
||||
}
|
||||
|
||||
function pow2523(o, i) {
|
||||
var c = gf();
|
||||
var a;
|
||||
for(a = 0; a < 16; ++a) {
|
||||
c[a] = i[a];
|
||||
}
|
||||
for(a = 250; a >= 0; --a) {
|
||||
S(c, c);
|
||||
if(a !== 1) {
|
||||
M(c, c, i);
|
||||
}
|
||||
}
|
||||
for(a = 0; a < 16; ++a) {
|
||||
o[a] = c[a];
|
||||
}
|
||||
}
|
||||
|
||||
function neq25519(a, b) {
|
||||
var c = new NativeBuffer(32);
|
||||
var d = new NativeBuffer(32);
|
||||
pack25519(c, a);
|
||||
pack25519(d, b);
|
||||
return crypto_verify_32(c, 0, d, 0);
|
||||
}
|
||||
|
||||
function crypto_verify_32(x, xi, y, yi) {
|
||||
return vn(x, xi, y, yi, 32);
|
||||
}
|
||||
|
||||
function vn(x, xi, y, yi, n) {
|
||||
var i, d = 0;
|
||||
for(i = 0; i < n; ++i) {
|
||||
d |= x[xi + i] ^ y[yi + i];
|
||||
}
|
||||
return (1 & ((d - 1) >>> 8)) - 1;
|
||||
}
|
||||
|
||||
function par25519(a) {
|
||||
var d = new NativeBuffer(32);
|
||||
pack25519(d, a);
|
||||
return d[0] & 1;
|
||||
}
|
||||
|
||||
function scalarmult(p, q, s) {
|
||||
var b, i;
|
||||
set25519(p[0], gf0);
|
||||
set25519(p[1], gf1);
|
||||
set25519(p[2], gf1);
|
||||
set25519(p[3], gf0);
|
||||
for(i = 255; i >= 0; --i) {
|
||||
b = (s[(i / 8)|0] >> (i & 7)) & 1;
|
||||
cswap(p, q, b);
|
||||
add(q, p);
|
||||
add(p, p);
|
||||
cswap(p, q, b);
|
||||
}
|
||||
}
|
||||
|
||||
function scalarbase(p, s) {
|
||||
var q = [gf(), gf(), gf(), gf()];
|
||||
set25519(q[0], X);
|
||||
set25519(q[1], Y);
|
||||
set25519(q[2], gf1);
|
||||
M(q[3], X, Y);
|
||||
scalarmult(p, q, s);
|
||||
}
|
||||
|
||||
function set25519(r, a) {
|
||||
var i;
|
||||
for(i = 0; i < 16; i++) {
|
||||
r[i] = a[i] | 0;
|
||||
}
|
||||
}
|
||||
|
||||
function inv25519(o, i) {
|
||||
var c = gf();
|
||||
var a;
|
||||
for(a = 0; a < 16; ++a) {
|
||||
c[a] = i[a];
|
||||
}
|
||||
for(a = 253; a >= 0; --a) {
|
||||
S(c, c);
|
||||
if(a !== 2 && a !== 4) {
|
||||
M(c, c, i);
|
||||
}
|
||||
}
|
||||
for(a = 0; a < 16; ++a) {
|
||||
o[a] = c[a];
|
||||
}
|
||||
}
|
||||
|
||||
function car25519(o) {
|
||||
var i, v, c = 1;
|
||||
for(i = 0; i < 16; ++i) {
|
||||
v = o[i] + c + 65535;
|
||||
c = Math.floor(v / 65536);
|
||||
o[i] = v - c * 65536;
|
||||
}
|
||||
o[0] += c - 1 + 37 * (c - 1);
|
||||
}
|
||||
|
||||
function sel25519(p, q, b) {
|
||||
var t, c = ~(b - 1);
|
||||
for(var i = 0; i < 16; ++i) {
|
||||
t = c & (p[i] ^ q[i]);
|
||||
p[i] ^= t;
|
||||
q[i] ^= t;
|
||||
}
|
||||
}
|
||||
|
||||
function gf(init) {
|
||||
var i, r = new Float64Array(16);
|
||||
if(init) {
|
||||
for(i = 0; i < init.length; ++i) {
|
||||
r[i] = init[i];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
function A(o, a, b) {
|
||||
for(var i = 0; i < 16; ++i) {
|
||||
o[i] = a[i] + b[i];
|
||||
}
|
||||
}
|
||||
|
||||
function Z(o, a, b) {
|
||||
for(var i = 0; i < 16; ++i) {
|
||||
o[i] = a[i] - b[i];
|
||||
}
|
||||
}
|
||||
|
||||
function S(o, a) {
|
||||
M(o, a, a);
|
||||
}
|
||||
|
||||
function M(o, a, b) {
|
||||
var v, c,
|
||||
t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
|
||||
t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
|
||||
t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
|
||||
t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
|
||||
b0 = b[0],
|
||||
b1 = b[1],
|
||||
b2 = b[2],
|
||||
b3 = b[3],
|
||||
b4 = b[4],
|
||||
b5 = b[5],
|
||||
b6 = b[6],
|
||||
b7 = b[7],
|
||||
b8 = b[8],
|
||||
b9 = b[9],
|
||||
b10 = b[10],
|
||||
b11 = b[11],
|
||||
b12 = b[12],
|
||||
b13 = b[13],
|
||||
b14 = b[14],
|
||||
b15 = b[15];
|
||||
|
||||
v = a[0];
|
||||
t0 += v * b0;
|
||||
t1 += v * b1;
|
||||
t2 += v * b2;
|
||||
t3 += v * b3;
|
||||
t4 += v * b4;
|
||||
t5 += v * b5;
|
||||
t6 += v * b6;
|
||||
t7 += v * b7;
|
||||
t8 += v * b8;
|
||||
t9 += v * b9;
|
||||
t10 += v * b10;
|
||||
t11 += v * b11;
|
||||
t12 += v * b12;
|
||||
t13 += v * b13;
|
||||
t14 += v * b14;
|
||||
t15 += v * b15;
|
||||
v = a[1];
|
||||
t1 += v * b0;
|
||||
t2 += v * b1;
|
||||
t3 += v * b2;
|
||||
t4 += v * b3;
|
||||
t5 += v * b4;
|
||||
t6 += v * b5;
|
||||
t7 += v * b6;
|
||||
t8 += v * b7;
|
||||
t9 += v * b8;
|
||||
t10 += v * b9;
|
||||
t11 += v * b10;
|
||||
t12 += v * b11;
|
||||
t13 += v * b12;
|
||||
t14 += v * b13;
|
||||
t15 += v * b14;
|
||||
t16 += v * b15;
|
||||
v = a[2];
|
||||
t2 += v * b0;
|
||||
t3 += v * b1;
|
||||
t4 += v * b2;
|
||||
t5 += v * b3;
|
||||
t6 += v * b4;
|
||||
t7 += v * b5;
|
||||
t8 += v * b6;
|
||||
t9 += v * b7;
|
||||
t10 += v * b8;
|
||||
t11 += v * b9;
|
||||
t12 += v * b10;
|
||||
t13 += v * b11;
|
||||
t14 += v * b12;
|
||||
t15 += v * b13;
|
||||
t16 += v * b14;
|
||||
t17 += v * b15;
|
||||
v = a[3];
|
||||
t3 += v * b0;
|
||||
t4 += v * b1;
|
||||
t5 += v * b2;
|
||||
t6 += v * b3;
|
||||
t7 += v * b4;
|
||||
t8 += v * b5;
|
||||
t9 += v * b6;
|
||||
t10 += v * b7;
|
||||
t11 += v * b8;
|
||||
t12 += v * b9;
|
||||
t13 += v * b10;
|
||||
t14 += v * b11;
|
||||
t15 += v * b12;
|
||||
t16 += v * b13;
|
||||
t17 += v * b14;
|
||||
t18 += v * b15;
|
||||
v = a[4];
|
||||
t4 += v * b0;
|
||||
t5 += v * b1;
|
||||
t6 += v * b2;
|
||||
t7 += v * b3;
|
||||
t8 += v * b4;
|
||||
t9 += v * b5;
|
||||
t10 += v * b6;
|
||||
t11 += v * b7;
|
||||
t12 += v * b8;
|
||||
t13 += v * b9;
|
||||
t14 += v * b10;
|
||||
t15 += v * b11;
|
||||
t16 += v * b12;
|
||||
t17 += v * b13;
|
||||
t18 += v * b14;
|
||||
t19 += v * b15;
|
||||
v = a[5];
|
||||
t5 += v * b0;
|
||||
t6 += v * b1;
|
||||
t7 += v * b2;
|
||||
t8 += v * b3;
|
||||
t9 += v * b4;
|
||||
t10 += v * b5;
|
||||
t11 += v * b6;
|
||||
t12 += v * b7;
|
||||
t13 += v * b8;
|
||||
t14 += v * b9;
|
||||
t15 += v * b10;
|
||||
t16 += v * b11;
|
||||
t17 += v * b12;
|
||||
t18 += v * b13;
|
||||
t19 += v * b14;
|
||||
t20 += v * b15;
|
||||
v = a[6];
|
||||
t6 += v * b0;
|
||||
t7 += v * b1;
|
||||
t8 += v * b2;
|
||||
t9 += v * b3;
|
||||
t10 += v * b4;
|
||||
t11 += v * b5;
|
||||
t12 += v * b6;
|
||||
t13 += v * b7;
|
||||
t14 += v * b8;
|
||||
t15 += v * b9;
|
||||
t16 += v * b10;
|
||||
t17 += v * b11;
|
||||
t18 += v * b12;
|
||||
t19 += v * b13;
|
||||
t20 += v * b14;
|
||||
t21 += v * b15;
|
||||
v = a[7];
|
||||
t7 += v * b0;
|
||||
t8 += v * b1;
|
||||
t9 += v * b2;
|
||||
t10 += v * b3;
|
||||
t11 += v * b4;
|
||||
t12 += v * b5;
|
||||
t13 += v * b6;
|
||||
t14 += v * b7;
|
||||
t15 += v * b8;
|
||||
t16 += v * b9;
|
||||
t17 += v * b10;
|
||||
t18 += v * b11;
|
||||
t19 += v * b12;
|
||||
t20 += v * b13;
|
||||
t21 += v * b14;
|
||||
t22 += v * b15;
|
||||
v = a[8];
|
||||
t8 += v * b0;
|
||||
t9 += v * b1;
|
||||
t10 += v * b2;
|
||||
t11 += v * b3;
|
||||
t12 += v * b4;
|
||||
t13 += v * b5;
|
||||
t14 += v * b6;
|
||||
t15 += v * b7;
|
||||
t16 += v * b8;
|
||||
t17 += v * b9;
|
||||
t18 += v * b10;
|
||||
t19 += v * b11;
|
||||
t20 += v * b12;
|
||||
t21 += v * b13;
|
||||
t22 += v * b14;
|
||||
t23 += v * b15;
|
||||
v = a[9];
|
||||
t9 += v * b0;
|
||||
t10 += v * b1;
|
||||
t11 += v * b2;
|
||||
t12 += v * b3;
|
||||
t13 += v * b4;
|
||||
t14 += v * b5;
|
||||
t15 += v * b6;
|
||||
t16 += v * b7;
|
||||
t17 += v * b8;
|
||||
t18 += v * b9;
|
||||
t19 += v * b10;
|
||||
t20 += v * b11;
|
||||
t21 += v * b12;
|
||||
t22 += v * b13;
|
||||
t23 += v * b14;
|
||||
t24 += v * b15;
|
||||
v = a[10];
|
||||
t10 += v * b0;
|
||||
t11 += v * b1;
|
||||
t12 += v * b2;
|
||||
t13 += v * b3;
|
||||
t14 += v * b4;
|
||||
t15 += v * b5;
|
||||
t16 += v * b6;
|
||||
t17 += v * b7;
|
||||
t18 += v * b8;
|
||||
t19 += v * b9;
|
||||
t20 += v * b10;
|
||||
t21 += v * b11;
|
||||
t22 += v * b12;
|
||||
t23 += v * b13;
|
||||
t24 += v * b14;
|
||||
t25 += v * b15;
|
||||
v = a[11];
|
||||
t11 += v * b0;
|
||||
t12 += v * b1;
|
||||
t13 += v * b2;
|
||||
t14 += v * b3;
|
||||
t15 += v * b4;
|
||||
t16 += v * b5;
|
||||
t17 += v * b6;
|
||||
t18 += v * b7;
|
||||
t19 += v * b8;
|
||||
t20 += v * b9;
|
||||
t21 += v * b10;
|
||||
t22 += v * b11;
|
||||
t23 += v * b12;
|
||||
t24 += v * b13;
|
||||
t25 += v * b14;
|
||||
t26 += v * b15;
|
||||
v = a[12];
|
||||
t12 += v * b0;
|
||||
t13 += v * b1;
|
||||
t14 += v * b2;
|
||||
t15 += v * b3;
|
||||
t16 += v * b4;
|
||||
t17 += v * b5;
|
||||
t18 += v * b6;
|
||||
t19 += v * b7;
|
||||
t20 += v * b8;
|
||||
t21 += v * b9;
|
||||
t22 += v * b10;
|
||||
t23 += v * b11;
|
||||
t24 += v * b12;
|
||||
t25 += v * b13;
|
||||
t26 += v * b14;
|
||||
t27 += v * b15;
|
||||
v = a[13];
|
||||
t13 += v * b0;
|
||||
t14 += v * b1;
|
||||
t15 += v * b2;
|
||||
t16 += v * b3;
|
||||
t17 += v * b4;
|
||||
t18 += v * b5;
|
||||
t19 += v * b6;
|
||||
t20 += v * b7;
|
||||
t21 += v * b8;
|
||||
t22 += v * b9;
|
||||
t23 += v * b10;
|
||||
t24 += v * b11;
|
||||
t25 += v * b12;
|
||||
t26 += v * b13;
|
||||
t27 += v * b14;
|
||||
t28 += v * b15;
|
||||
v = a[14];
|
||||
t14 += v * b0;
|
||||
t15 += v * b1;
|
||||
t16 += v * b2;
|
||||
t17 += v * b3;
|
||||
t18 += v * b4;
|
||||
t19 += v * b5;
|
||||
t20 += v * b6;
|
||||
t21 += v * b7;
|
||||
t22 += v * b8;
|
||||
t23 += v * b9;
|
||||
t24 += v * b10;
|
||||
t25 += v * b11;
|
||||
t26 += v * b12;
|
||||
t27 += v * b13;
|
||||
t28 += v * b14;
|
||||
t29 += v * b15;
|
||||
v = a[15];
|
||||
t15 += v * b0;
|
||||
t16 += v * b1;
|
||||
t17 += v * b2;
|
||||
t18 += v * b3;
|
||||
t19 += v * b4;
|
||||
t20 += v * b5;
|
||||
t21 += v * b6;
|
||||
t22 += v * b7;
|
||||
t23 += v * b8;
|
||||
t24 += v * b9;
|
||||
t25 += v * b10;
|
||||
t26 += v * b11;
|
||||
t27 += v * b12;
|
||||
t28 += v * b13;
|
||||
t29 += v * b14;
|
||||
t30 += v * b15;
|
||||
|
||||
t0 += 38 * t16;
|
||||
t1 += 38 * t17;
|
||||
t2 += 38 * t18;
|
||||
t3 += 38 * t19;
|
||||
t4 += 38 * t20;
|
||||
t5 += 38 * t21;
|
||||
t6 += 38 * t22;
|
||||
t7 += 38 * t23;
|
||||
t8 += 38 * t24;
|
||||
t9 += 38 * t25;
|
||||
t10 += 38 * t26;
|
||||
t11 += 38 * t27;
|
||||
t12 += 38 * t28;
|
||||
t13 += 38 * t29;
|
||||
t14 += 38 * t30;
|
||||
// t15 left as is
|
||||
|
||||
// first car
|
||||
c = 1;
|
||||
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
|
||||
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
|
||||
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
|
||||
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
|
||||
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
|
||||
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
|
||||
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
|
||||
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
|
||||
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
|
||||
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
|
||||
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
|
||||
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
|
||||
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
|
||||
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
|
||||
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
|
||||
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
|
||||
t0 += c-1 + 37 * (c-1);
|
||||
|
||||
// second car
|
||||
c = 1;
|
||||
v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
|
||||
v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
|
||||
v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
|
||||
v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
|
||||
v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
|
||||
v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
|
||||
v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
|
||||
v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
|
||||
v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
|
||||
v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
|
||||
v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
|
||||
v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
|
||||
v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
|
||||
v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
|
||||
v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
|
||||
v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
|
||||
t0 += c-1 + 37 * (c-1);
|
||||
|
||||
o[ 0] = t0;
|
||||
o[ 1] = t1;
|
||||
o[ 2] = t2;
|
||||
o[ 3] = t3;
|
||||
o[ 4] = t4;
|
||||
o[ 5] = t5;
|
||||
o[ 6] = t6;
|
||||
o[ 7] = t7;
|
||||
o[ 8] = t8;
|
||||
o[ 9] = t9;
|
||||
o[10] = t10;
|
||||
o[11] = t11;
|
||||
o[12] = t12;
|
||||
o[13] = t13;
|
||||
o[14] = t14;
|
||||
o[15] = t15;
|
||||
}
|
13
node_modules/node-forge/lib/forge.js
generated
vendored
Normal file
13
node_modules/node-forge/lib/forge.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Node.js module for Forge.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright 2011-2016 Digital Bazaar, Inc.
|
||||
*/
|
||||
module.exports = {
|
||||
// default options
|
||||
options: {
|
||||
usePureJavaScript: false
|
||||
}
|
||||
};
|
149
node_modules/node-forge/lib/form.js
generated
vendored
Normal file
149
node_modules/node-forge/lib/form.js
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Functions for manipulating web forms.
|
||||
*
|
||||
* @author David I. Lehn <dlehn@digitalbazaar.com>
|
||||
* @author Dave Longley
|
||||
* @author Mike Johnson
|
||||
*
|
||||
* Copyright (c) 2011-2014 Digital Bazaar, Inc. All rights reserved.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
|
||||
/* Form API */
|
||||
var form = module.exports = forge.form = forge.form || {};
|
||||
|
||||
(function($) {
|
||||
|
||||
/**
|
||||
* Regex for parsing a single name property (handles array brackets).
|
||||
*/
|
||||
var _regex = /([^\[]*?)\[(.*?)\]/g;
|
||||
|
||||
/**
|
||||
* Parses a single name property into an array with the name and any
|
||||
* array indices.
|
||||
*
|
||||
* @param name the name to parse.
|
||||
*
|
||||
* @return the array of the name and its array indices in order.
|
||||
*/
|
||||
var _parseName = function(name) {
|
||||
var rval = [];
|
||||
|
||||
var matches;
|
||||
while(!!(matches = _regex.exec(name))) {
|
||||
if(matches[1].length > 0) {
|
||||
rval.push(matches[1]);
|
||||
}
|
||||
if(matches.length >= 2) {
|
||||
rval.push(matches[2]);
|
||||
}
|
||||
}
|
||||
if(rval.length === 0) {
|
||||
rval.push(name);
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a field from the given form to the given object.
|
||||
*
|
||||
* @param obj the object.
|
||||
* @param names the field as an array of object property names.
|
||||
* @param value the value of the field.
|
||||
* @param dict a dictionary of names to replace.
|
||||
*/
|
||||
var _addField = function(obj, names, value, dict) {
|
||||
// combine array names that fall within square brackets
|
||||
var tmp = [];
|
||||
for(var i = 0; i < names.length; ++i) {
|
||||
// check name for starting square bracket but no ending one
|
||||
var name = names[i];
|
||||
if(name.indexOf('[') !== -1 && name.indexOf(']') === -1 &&
|
||||
i < names.length - 1) {
|
||||
do {
|
||||
name += '.' + names[++i];
|
||||
} while(i < names.length - 1 && names[i].indexOf(']') === -1);
|
||||
}
|
||||
tmp.push(name);
|
||||
}
|
||||
names = tmp;
|
||||
|
||||
// split out array indexes
|
||||
var tmp = [];
|
||||
$.each(names, function(n, name) {
|
||||
tmp = tmp.concat(_parseName(name));
|
||||
});
|
||||
names = tmp;
|
||||
|
||||
// iterate over object property names until value is set
|
||||
$.each(names, function(n, name) {
|
||||
// do dictionary name replacement
|
||||
if(dict && name.length !== 0 && name in dict) {
|
||||
name = dict[name];
|
||||
}
|
||||
|
||||
// blank name indicates appending to an array, set name to
|
||||
// new last index of array
|
||||
if(name.length === 0) {
|
||||
name = obj.length;
|
||||
}
|
||||
|
||||
// value already exists, append value
|
||||
if(obj[name]) {
|
||||
// last name in the field
|
||||
if(n == names.length - 1) {
|
||||
// more than one value, so convert into an array
|
||||
if(!$.isArray(obj[name])) {
|
||||
obj[name] = [obj[name]];
|
||||
}
|
||||
obj[name].push(value);
|
||||
} else {
|
||||
// not last name, go deeper into object
|
||||
obj = obj[name];
|
||||
}
|
||||
} else if(n == names.length - 1) {
|
||||
// new value, last name in the field, set value
|
||||
obj[name] = value;
|
||||
} else {
|
||||
// new value, not last name, go deeper
|
||||
// get next name
|
||||
var next = names[n + 1];
|
||||
|
||||
// blank next value indicates array-appending, so create array
|
||||
if(next.length === 0) {
|
||||
obj[name] = [];
|
||||
} else {
|
||||
// if next name is a number create an array, otherwise a map
|
||||
var isNum = ((next - 0) == next && next.length > 0);
|
||||
obj[name] = isNum ? [] : {};
|
||||
}
|
||||
obj = obj[name];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Serializes a form to a JSON object. Object properties will be separated
|
||||
* using the given separator (defaults to '.') and by square brackets.
|
||||
*
|
||||
* @param input the jquery form to serialize.
|
||||
* @param sep the object-property separator (defaults to '.').
|
||||
* @param dict a dictionary of names to replace (name=replace).
|
||||
*
|
||||
* @return the JSON-serialized form.
|
||||
*/
|
||||
form.serialize = function(input, sep, dict) {
|
||||
var rval = {};
|
||||
|
||||
// add all fields in the form to the object
|
||||
sep = sep || '.';
|
||||
$.each(input.serializeArray(), function() {
|
||||
_addField(rval, this.name.split(sep), this.value || '', dict);
|
||||
});
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
})(jQuery);
|
146
node_modules/node-forge/lib/hmac.js
generated
vendored
Normal file
146
node_modules/node-forge/lib/hmac.js
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
/**
|
||||
* Hash-based Message Authentication Code implementation. Requires a message
|
||||
* digest object that can be obtained, for example, from forge.md.sha1 or
|
||||
* forge.md.md5.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2012 Digital Bazaar, Inc. All rights reserved.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
/* HMAC API */
|
||||
var hmac = module.exports = forge.hmac = forge.hmac || {};
|
||||
|
||||
/**
|
||||
* Creates an HMAC object that uses the given message digest object.
|
||||
*
|
||||
* @return an HMAC object.
|
||||
*/
|
||||
hmac.create = function() {
|
||||
// the hmac key to use
|
||||
var _key = null;
|
||||
|
||||
// the message digest to use
|
||||
var _md = null;
|
||||
|
||||
// the inner padding
|
||||
var _ipadding = null;
|
||||
|
||||
// the outer padding
|
||||
var _opadding = null;
|
||||
|
||||
// hmac context
|
||||
var ctx = {};
|
||||
|
||||
/**
|
||||
* Starts or restarts the HMAC with the given key and message digest.
|
||||
*
|
||||
* @param md the message digest to use, null to reuse the previous one,
|
||||
* a string to use builtin 'sha1', 'md5', 'sha256'.
|
||||
* @param key the key to use as a string, array of bytes, byte buffer,
|
||||
* or null to reuse the previous key.
|
||||
*/
|
||||
ctx.start = function(md, key) {
|
||||
if(md !== null) {
|
||||
if(typeof md === 'string') {
|
||||
// create builtin message digest
|
||||
md = md.toLowerCase();
|
||||
if(md in forge.md.algorithms) {
|
||||
_md = forge.md.algorithms[md].create();
|
||||
} else {
|
||||
throw new Error('Unknown hash algorithm "' + md + '"');
|
||||
}
|
||||
} else {
|
||||
// store message digest
|
||||
_md = md;
|
||||
}
|
||||
}
|
||||
|
||||
if(key === null) {
|
||||
// reuse previous key
|
||||
key = _key;
|
||||
} else {
|
||||
if(typeof key === 'string') {
|
||||
// convert string into byte buffer
|
||||
key = forge.util.createBuffer(key);
|
||||
} else if(forge.util.isArray(key)) {
|
||||
// convert byte array into byte buffer
|
||||
var tmp = key;
|
||||
key = forge.util.createBuffer();
|
||||
for(var i = 0; i < tmp.length; ++i) {
|
||||
key.putByte(tmp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// if key is longer than blocksize, hash it
|
||||
var keylen = key.length();
|
||||
if(keylen > _md.blockLength) {
|
||||
_md.start();
|
||||
_md.update(key.bytes());
|
||||
key = _md.digest();
|
||||
}
|
||||
|
||||
// mix key into inner and outer padding
|
||||
// ipadding = [0x36 * blocksize] ^ key
|
||||
// opadding = [0x5C * blocksize] ^ key
|
||||
_ipadding = forge.util.createBuffer();
|
||||
_opadding = forge.util.createBuffer();
|
||||
keylen = key.length();
|
||||
for(var i = 0; i < keylen; ++i) {
|
||||
var tmp = key.at(i);
|
||||
_ipadding.putByte(0x36 ^ tmp);
|
||||
_opadding.putByte(0x5C ^ tmp);
|
||||
}
|
||||
|
||||
// if key is shorter than blocksize, add additional padding
|
||||
if(keylen < _md.blockLength) {
|
||||
var tmp = _md.blockLength - keylen;
|
||||
for(var i = 0; i < tmp; ++i) {
|
||||
_ipadding.putByte(0x36);
|
||||
_opadding.putByte(0x5C);
|
||||
}
|
||||
}
|
||||
_key = key;
|
||||
_ipadding = _ipadding.bytes();
|
||||
_opadding = _opadding.bytes();
|
||||
}
|
||||
|
||||
// digest is done like so: hash(opadding | hash(ipadding | message))
|
||||
|
||||
// prepare to do inner hash
|
||||
// hash(ipadding | message)
|
||||
_md.start();
|
||||
_md.update(_ipadding);
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the HMAC with the given message bytes.
|
||||
*
|
||||
* @param bytes the bytes to update with.
|
||||
*/
|
||||
ctx.update = function(bytes) {
|
||||
_md.update(bytes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Produces the Message Authentication Code (MAC).
|
||||
*
|
||||
* @return a byte buffer containing the digest value.
|
||||
*/
|
||||
ctx.getMac = function() {
|
||||
// digest is done like so: hash(opadding | hash(ipadding | message))
|
||||
// here we do the outer hashing
|
||||
var inner = _md.digest().bytes();
|
||||
_md.start();
|
||||
_md.update(_opadding);
|
||||
_md.update(inner);
|
||||
return _md.digest();
|
||||
};
|
||||
// alias for getMac
|
||||
ctx.digest = ctx.getMac;
|
||||
|
||||
return ctx;
|
||||
};
|
1364
node_modules/node-forge/lib/http.js
generated
vendored
Normal file
1364
node_modules/node-forge/lib/http.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
node_modules/node-forge/lib/index.all.js
generated
vendored
Normal file
16
node_modules/node-forge/lib/index.all.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Node.js module for Forge with extra utils and networking.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright 2011-2016 Digital Bazaar, Inc.
|
||||
*/
|
||||
module.exports = require('./forge');
|
||||
// require core forge
|
||||
require('./index');
|
||||
// additional utils and networking support
|
||||
require('./form');
|
||||
require('./socket');
|
||||
require('./tlssocket');
|
||||
require('./http');
|
||||
require('./xhr');
|
35
node_modules/node-forge/lib/index.js
generated
vendored
Normal file
35
node_modules/node-forge/lib/index.js
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Node.js module for Forge.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright 2011-2016 Digital Bazaar, Inc.
|
||||
*/
|
||||
module.exports = require('./forge');
|
||||
require('./aes');
|
||||
require('./aesCipherSuites');
|
||||
require('./asn1');
|
||||
require('./cipher');
|
||||
require('./debug');
|
||||
require('./des');
|
||||
require('./ed25519');
|
||||
require('./hmac');
|
||||
require('./kem');
|
||||
require('./log');
|
||||
require('./md.all');
|
||||
require('./mgf1');
|
||||
require('./pbkdf2');
|
||||
require('./pem');
|
||||
require('./pkcs1');
|
||||
require('./pkcs12');
|
||||
require('./pkcs7');
|
||||
require('./pki');
|
||||
require('./prime');
|
||||
require('./prng');
|
||||
require('./pss');
|
||||
require('./random');
|
||||
require('./rc2');
|
||||
require('./ssh');
|
||||
require('./task');
|
||||
require('./tls');
|
||||
require('./util');
|
1264
node_modules/node-forge/lib/jsbn.js
generated
vendored
Normal file
1264
node_modules/node-forge/lib/jsbn.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
168
node_modules/node-forge/lib/kem.js
generated
vendored
Normal file
168
node_modules/node-forge/lib/kem.js
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Javascript implementation of RSA-KEM.
|
||||
*
|
||||
* @author Lautaro Cozzani Rodriguez
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2014 Lautaro Cozzani <lautaro.cozzani@scytl.com>
|
||||
* Copyright (c) 2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
require('./random');
|
||||
require('./jsbn');
|
||||
|
||||
module.exports = forge.kem = forge.kem || {};
|
||||
|
||||
var BigInteger = forge.jsbn.BigInteger;
|
||||
|
||||
/**
|
||||
* The API for the RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
|
||||
*/
|
||||
forge.kem.rsa = {};
|
||||
|
||||
/**
|
||||
* Creates an RSA KEM API object for generating a secret asymmetric key.
|
||||
*
|
||||
* The symmetric key may be generated via a call to 'encrypt', which will
|
||||
* produce a ciphertext to be transmitted to the recipient and a key to be
|
||||
* kept secret. The ciphertext is a parameter to be passed to 'decrypt' which
|
||||
* will produce the same secret key for the recipient to use to decrypt a
|
||||
* message that was encrypted with the secret key.
|
||||
*
|
||||
* @param kdf the KDF API to use (eg: new forge.kem.kdf1()).
|
||||
* @param options the options to use.
|
||||
* [prng] a custom crypto-secure pseudo-random number generator to use,
|
||||
* that must define "getBytesSync".
|
||||
*/
|
||||
forge.kem.rsa.create = function(kdf, options) {
|
||||
options = options || {};
|
||||
var prng = options.prng || forge.random;
|
||||
|
||||
var kem = {};
|
||||
|
||||
/**
|
||||
* Generates a secret key and its encapsulation.
|
||||
*
|
||||
* @param publicKey the RSA public key to encrypt with.
|
||||
* @param keyLength the length, in bytes, of the secret key to generate.
|
||||
*
|
||||
* @return an object with:
|
||||
* encapsulation: the ciphertext for generating the secret key, as a
|
||||
* binary-encoded string of bytes.
|
||||
* key: the secret key to use for encrypting a message.
|
||||
*/
|
||||
kem.encrypt = function(publicKey, keyLength) {
|
||||
// generate a random r where 1 > r > n
|
||||
var byteLength = Math.ceil(publicKey.n.bitLength() / 8);
|
||||
var r;
|
||||
do {
|
||||
r = new BigInteger(
|
||||
forge.util.bytesToHex(prng.getBytesSync(byteLength)),
|
||||
16).mod(publicKey.n);
|
||||
} while(r.equals(BigInteger.ZERO));
|
||||
|
||||
// prepend r with zeros
|
||||
r = forge.util.hexToBytes(r.toString(16));
|
||||
var zeros = byteLength - r.length;
|
||||
if(zeros > 0) {
|
||||
r = forge.util.fillString(String.fromCharCode(0), zeros) + r;
|
||||
}
|
||||
|
||||
// encrypt the random
|
||||
var encapsulation = publicKey.encrypt(r, 'NONE');
|
||||
|
||||
// generate the secret key
|
||||
var key = kdf.generate(r, keyLength);
|
||||
|
||||
return {encapsulation: encapsulation, key: key};
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypts an encapsulated secret key.
|
||||
*
|
||||
* @param privateKey the RSA private key to decrypt with.
|
||||
* @param encapsulation the ciphertext for generating the secret key, as
|
||||
* a binary-encoded string of bytes.
|
||||
* @param keyLength the length, in bytes, of the secret key to generate.
|
||||
*
|
||||
* @return the secret key as a binary-encoded string of bytes.
|
||||
*/
|
||||
kem.decrypt = function(privateKey, encapsulation, keyLength) {
|
||||
// decrypt the encapsulation and generate the secret key
|
||||
var r = privateKey.decrypt(encapsulation, 'NONE');
|
||||
return kdf.generate(r, keyLength);
|
||||
};
|
||||
|
||||
return kem;
|
||||
};
|
||||
|
||||
// TODO: add forge.kem.kdf.create('KDF1', {md: ..., ...}) API?
|
||||
|
||||
/**
|
||||
* Creates a key derivation API object that implements KDF1 per ISO 18033-2.
|
||||
*
|
||||
* @param md the hash API to use.
|
||||
* @param [digestLength] an optional digest length that must be positive and
|
||||
* less than or equal to md.digestLength.
|
||||
*
|
||||
* @return a KDF1 API object.
|
||||
*/
|
||||
forge.kem.kdf1 = function(md, digestLength) {
|
||||
_createKDF(this, md, 0, digestLength || md.digestLength);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a key derivation API object that implements KDF2 per ISO 18033-2.
|
||||
*
|
||||
* @param md the hash API to use.
|
||||
* @param [digestLength] an optional digest length that must be positive and
|
||||
* less than or equal to md.digestLength.
|
||||
*
|
||||
* @return a KDF2 API object.
|
||||
*/
|
||||
forge.kem.kdf2 = function(md, digestLength) {
|
||||
_createKDF(this, md, 1, digestLength || md.digestLength);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a KDF1 or KDF2 API object.
|
||||
*
|
||||
* @param md the hash API to use.
|
||||
* @param counterStart the starting index for the counter.
|
||||
* @param digestLength the digest length to use.
|
||||
*
|
||||
* @return the KDF API object.
|
||||
*/
|
||||
function _createKDF(kdf, md, counterStart, digestLength) {
|
||||
/**
|
||||
* Generate a key of the specified length.
|
||||
*
|
||||
* @param x the binary-encoded byte string to generate a key from.
|
||||
* @param length the number of bytes to generate (the size of the key).
|
||||
*
|
||||
* @return the key as a binary-encoded string.
|
||||
*/
|
||||
kdf.generate = function(x, length) {
|
||||
var key = new forge.util.ByteBuffer();
|
||||
|
||||
// run counter from counterStart to ceil(length / Hash.len)
|
||||
var k = Math.ceil(length / digestLength) + counterStart;
|
||||
|
||||
var c = new forge.util.ByteBuffer();
|
||||
for(var i = counterStart; i < k; ++i) {
|
||||
// I2OSP(i, 4): convert counter to an octet string of 4 octets
|
||||
c.putInt32(i);
|
||||
|
||||
// digest 'x' and the counter and add the result to the key
|
||||
md.start();
|
||||
md.update(x + c.getBytes());
|
||||
var hash = md.digest();
|
||||
key.putBytes(hash.getBytes(digestLength));
|
||||
}
|
||||
|
||||
// truncate to the correct key length
|
||||
key.truncate(key.length() - length);
|
||||
return key.getBytes();
|
||||
};
|
||||
}
|
317
node_modules/node-forge/lib/log.js
generated
vendored
Normal file
317
node_modules/node-forge/lib/log.js
generated
vendored
Normal file
@ -0,0 +1,317 @@
|
||||
/**
|
||||
* Cross-browser support for logging in a web application.
|
||||
*
|
||||
* @author David I. Lehn <dlehn@digitalbazaar.com>
|
||||
*
|
||||
* Copyright (c) 2008-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
/* LOG API */
|
||||
module.exports = forge.log = forge.log || {};
|
||||
|
||||
/**
|
||||
* Application logging system.
|
||||
*
|
||||
* Each logger level available as it's own function of the form:
|
||||
* forge.log.level(category, args...)
|
||||
* The category is an arbitrary string, and the args are the same as
|
||||
* Firebug's console.log API. By default the call will be output as:
|
||||
* 'LEVEL [category] <args[0]>, args[1], ...'
|
||||
* This enables proper % formatting via the first argument.
|
||||
* Each category is enabled by default but can be enabled or disabled with
|
||||
* the setCategoryEnabled() function.
|
||||
*/
|
||||
// list of known levels
|
||||
forge.log.levels = [
|
||||
'none', 'error', 'warning', 'info', 'debug', 'verbose', 'max'];
|
||||
// info on the levels indexed by name:
|
||||
// index: level index
|
||||
// name: uppercased display name
|
||||
var sLevelInfo = {};
|
||||
// list of loggers
|
||||
var sLoggers = [];
|
||||
/**
|
||||
* Standard console logger. If no console support is enabled this will
|
||||
* remain null. Check before using.
|
||||
*/
|
||||
var sConsoleLogger = null;
|
||||
|
||||
// logger flags
|
||||
/**
|
||||
* Lock the level at the current value. Used in cases where user config may
|
||||
* set the level such that only critical messages are seen but more verbose
|
||||
* messages are needed for debugging or other purposes.
|
||||
*/
|
||||
forge.log.LEVEL_LOCKED = (1 << 1);
|
||||
/**
|
||||
* Always call log function. By default, the logging system will check the
|
||||
* message level against logger.level before calling the log function. This
|
||||
* flag allows the function to do its own check.
|
||||
*/
|
||||
forge.log.NO_LEVEL_CHECK = (1 << 2);
|
||||
/**
|
||||
* Perform message interpolation with the passed arguments. "%" style
|
||||
* fields in log messages will be replaced by arguments as needed. Some
|
||||
* loggers, such as Firebug, may do this automatically. The original log
|
||||
* message will be available as 'message' and the interpolated version will
|
||||
* be available as 'fullMessage'.
|
||||
*/
|
||||
forge.log.INTERPOLATE = (1 << 3);
|
||||
|
||||
// setup each log level
|
||||
for(var i = 0; i < forge.log.levels.length; ++i) {
|
||||
var level = forge.log.levels[i];
|
||||
sLevelInfo[level] = {
|
||||
index: i,
|
||||
name: level.toUpperCase()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Message logger. Will dispatch a message to registered loggers as needed.
|
||||
*
|
||||
* @param message message object
|
||||
*/
|
||||
forge.log.logMessage = function(message) {
|
||||
var messageLevelIndex = sLevelInfo[message.level].index;
|
||||
for(var i = 0; i < sLoggers.length; ++i) {
|
||||
var logger = sLoggers[i];
|
||||
if(logger.flags & forge.log.NO_LEVEL_CHECK) {
|
||||
logger.f(message);
|
||||
} else {
|
||||
// get logger level
|
||||
var loggerLevelIndex = sLevelInfo[logger.level].index;
|
||||
// check level
|
||||
if(messageLevelIndex <= loggerLevelIndex) {
|
||||
// message critical enough, call logger
|
||||
logger.f(logger, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the 'standard' key on a message object to:
|
||||
* "LEVEL [category] " + message
|
||||
*
|
||||
* @param message a message log object
|
||||
*/
|
||||
forge.log.prepareStandard = function(message) {
|
||||
if(!('standard' in message)) {
|
||||
message.standard =
|
||||
sLevelInfo[message.level].name +
|
||||
//' ' + +message.timestamp +
|
||||
' [' + message.category + '] ' +
|
||||
message.message;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the 'full' key on a message object to the original message
|
||||
* interpolated via % formatting with the message arguments.
|
||||
*
|
||||
* @param message a message log object.
|
||||
*/
|
||||
forge.log.prepareFull = function(message) {
|
||||
if(!('full' in message)) {
|
||||
// copy args and insert message at the front
|
||||
var args = [message.message];
|
||||
args = args.concat([] || message['arguments']);
|
||||
// format the message
|
||||
message.full = forge.util.format.apply(this, args);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Applies both preparseStandard() and prepareFull() to a message object and
|
||||
* store result in 'standardFull'.
|
||||
*
|
||||
* @param message a message log object.
|
||||
*/
|
||||
forge.log.prepareStandardFull = function(message) {
|
||||
if(!('standardFull' in message)) {
|
||||
// FIXME implement 'standardFull' logging
|
||||
forge.log.prepareStandard(message);
|
||||
message.standardFull = message.standard;
|
||||
}
|
||||
};
|
||||
|
||||
// create log level functions
|
||||
if(true) {
|
||||
// levels for which we want functions
|
||||
var levels = ['error', 'warning', 'info', 'debug', 'verbose'];
|
||||
for(var i = 0; i < levels.length; ++i) {
|
||||
// wrap in a function to ensure proper level var is passed
|
||||
(function(level) {
|
||||
// create function for this level
|
||||
forge.log[level] = function(category, message/*, args...*/) {
|
||||
// convert arguments to real array, remove category and message
|
||||
var args = Array.prototype.slice.call(arguments).slice(2);
|
||||
// create message object
|
||||
// Note: interpolation and standard formatting is done lazily
|
||||
var msg = {
|
||||
timestamp: new Date(),
|
||||
level: level,
|
||||
category: category,
|
||||
message: message,
|
||||
'arguments': args
|
||||
/*standard*/
|
||||
/*full*/
|
||||
/*fullMessage*/
|
||||
};
|
||||
// process this message
|
||||
forge.log.logMessage(msg);
|
||||
};
|
||||
})(levels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new logger with specified custom logging function.
|
||||
*
|
||||
* The logging function has a signature of:
|
||||
* function(logger, message)
|
||||
* logger: current logger
|
||||
* message: object:
|
||||
* level: level id
|
||||
* category: category
|
||||
* message: string message
|
||||
* arguments: Array of extra arguments
|
||||
* fullMessage: interpolated message and arguments if INTERPOLATE flag set
|
||||
*
|
||||
* @param logFunction a logging function which takes a log message object
|
||||
* as a parameter.
|
||||
*
|
||||
* @return a logger object.
|
||||
*/
|
||||
forge.log.makeLogger = function(logFunction) {
|
||||
var logger = {
|
||||
flags: 0,
|
||||
f: logFunction
|
||||
};
|
||||
forge.log.setLevel(logger, 'none');
|
||||
return logger;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the current log level on a logger.
|
||||
*
|
||||
* @param logger the target logger.
|
||||
* @param level the new maximum log level as a string.
|
||||
*
|
||||
* @return true if set, false if not.
|
||||
*/
|
||||
forge.log.setLevel = function(logger, level) {
|
||||
var rval = false;
|
||||
if(logger && !(logger.flags & forge.log.LEVEL_LOCKED)) {
|
||||
for(var i = 0; i < forge.log.levels.length; ++i) {
|
||||
var aValidLevel = forge.log.levels[i];
|
||||
if(level == aValidLevel) {
|
||||
// set level
|
||||
logger.level = level;
|
||||
rval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Locks the log level at its current value.
|
||||
*
|
||||
* @param logger the target logger.
|
||||
* @param lock boolean lock value, default to true.
|
||||
*/
|
||||
forge.log.lock = function(logger, lock) {
|
||||
if(typeof lock === 'undefined' || lock) {
|
||||
logger.flags |= forge.log.LEVEL_LOCKED;
|
||||
} else {
|
||||
logger.flags &= ~forge.log.LEVEL_LOCKED;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a logger.
|
||||
*
|
||||
* @param logger the logger object.
|
||||
*/
|
||||
forge.log.addLogger = function(logger) {
|
||||
sLoggers.push(logger);
|
||||
};
|
||||
|
||||
// setup the console logger if possible, else create fake console.log
|
||||
if(typeof(console) !== 'undefined' && 'log' in console) {
|
||||
var logger;
|
||||
if(console.error && console.warn && console.info && console.debug) {
|
||||
// looks like Firebug-style logging is available
|
||||
// level handlers map
|
||||
var levelHandlers = {
|
||||
error: console.error,
|
||||
warning: console.warn,
|
||||
info: console.info,
|
||||
debug: console.debug,
|
||||
verbose: console.debug
|
||||
};
|
||||
var f = function(logger, message) {
|
||||
forge.log.prepareStandard(message);
|
||||
var handler = levelHandlers[message.level];
|
||||
// prepend standard message and concat args
|
||||
var args = [message.standard];
|
||||
args = args.concat(message['arguments'].slice());
|
||||
// apply to low-level console function
|
||||
handler.apply(console, args);
|
||||
};
|
||||
logger = forge.log.makeLogger(f);
|
||||
} else {
|
||||
// only appear to have basic console.log
|
||||
var f = function(logger, message) {
|
||||
forge.log.prepareStandardFull(message);
|
||||
console.log(message.standardFull);
|
||||
};
|
||||
logger = forge.log.makeLogger(f);
|
||||
}
|
||||
forge.log.setLevel(logger, 'debug');
|
||||
forge.log.addLogger(logger);
|
||||
sConsoleLogger = logger;
|
||||
} else {
|
||||
// define fake console.log to avoid potential script errors on
|
||||
// browsers that do not have console logging
|
||||
console = {
|
||||
log: function() {}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for logging control query vars.
|
||||
*
|
||||
* console.level=<level-name>
|
||||
* Set's the console log level by name. Useful to override defaults and
|
||||
* allow more verbose logging before a user config is loaded.
|
||||
*
|
||||
* console.lock=<true|false>
|
||||
* Lock the console log level at whatever level it is set at. This is run
|
||||
* after console.level is processed. Useful to force a level of verbosity
|
||||
* that could otherwise be limited by a user config.
|
||||
*/
|
||||
if(sConsoleLogger !== null) {
|
||||
var query = forge.util.getQueryVariables();
|
||||
if('console.level' in query) {
|
||||
// set with last value
|
||||
forge.log.setLevel(
|
||||
sConsoleLogger, query['console.level'].slice(-1)[0]);
|
||||
}
|
||||
if('console.lock' in query) {
|
||||
// set with last value
|
||||
var lock = query['console.lock'].slice(-1)[0];
|
||||
if(lock == 'true') {
|
||||
forge.log.lock(sConsoleLogger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// provide public access to console logger
|
||||
forge.log.consoleLogger = sConsoleLogger;
|
13
node_modules/node-forge/lib/md.all.js
generated
vendored
Normal file
13
node_modules/node-forge/lib/md.all.js
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Node.js module for all known Forge message digests.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright 2011-2017 Digital Bazaar, Inc.
|
||||
*/
|
||||
module.exports = require('./md');
|
||||
|
||||
require('./md5');
|
||||
require('./sha1');
|
||||
require('./sha256');
|
||||
require('./sha512');
|
11
node_modules/node-forge/lib/md.js
generated
vendored
Normal file
11
node_modules/node-forge/lib/md.js
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Node.js module for Forge message digests.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright 2011-2017 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
|
||||
module.exports = forge.md = forge.md || {};
|
||||
forge.md.algorithms = forge.md.algorithms || {};
|
289
node_modules/node-forge/lib/md5.js
generated
vendored
Normal file
289
node_modules/node-forge/lib/md5.js
generated
vendored
Normal file
@ -0,0 +1,289 @@
|
||||
/**
|
||||
* Message Digest Algorithm 5 with 128-bit digest (MD5) implementation.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
var md5 = module.exports = forge.md5 = forge.md5 || {};
|
||||
forge.md.md5 = forge.md.algorithms.md5 = md5;
|
||||
|
||||
/**
|
||||
* Creates an MD5 message digest object.
|
||||
*
|
||||
* @return a message digest object.
|
||||
*/
|
||||
md5.create = function() {
|
||||
// do initialization as necessary
|
||||
if(!_initialized) {
|
||||
_init();
|
||||
}
|
||||
|
||||
// MD5 state contains four 32-bit integers
|
||||
var _state = null;
|
||||
|
||||
// input buffer
|
||||
var _input = forge.util.createBuffer();
|
||||
|
||||
// used for word storage
|
||||
var _w = new Array(16);
|
||||
|
||||
// message digest object
|
||||
var md = {
|
||||
algorithm: 'md5',
|
||||
blockLength: 64,
|
||||
digestLength: 16,
|
||||
// 56-bit length of message so far (does not including padding)
|
||||
messageLength: 0,
|
||||
// true message length
|
||||
fullMessageLength: null,
|
||||
// size of message length in bytes
|
||||
messageLengthSize: 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the digest.
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.start = function() {
|
||||
// up to 56-bit message length for convenience
|
||||
md.messageLength = 0;
|
||||
|
||||
// full message length (set md.messageLength64 for backwards-compatibility)
|
||||
md.fullMessageLength = md.messageLength64 = [];
|
||||
var int32s = md.messageLengthSize / 4;
|
||||
for(var i = 0; i < int32s; ++i) {
|
||||
md.fullMessageLength.push(0);
|
||||
}
|
||||
_input = forge.util.createBuffer();
|
||||
_state = {
|
||||
h0: 0x67452301,
|
||||
h1: 0xEFCDAB89,
|
||||
h2: 0x98BADCFE,
|
||||
h3: 0x10325476
|
||||
};
|
||||
return md;
|
||||
};
|
||||
// start digest automatically for first time
|
||||
md.start();
|
||||
|
||||
/**
|
||||
* Updates the digest with the given message input. The given input can
|
||||
* treated as raw input (no encoding will be applied) or an encoding of
|
||||
* 'utf8' maybe given to encode the input using UTF-8.
|
||||
*
|
||||
* @param msg the message input to update with.
|
||||
* @param encoding the encoding to use (default: 'raw', other: 'utf8').
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.update = function(msg, encoding) {
|
||||
if(encoding === 'utf8') {
|
||||
msg = forge.util.encodeUtf8(msg);
|
||||
}
|
||||
|
||||
// update message length
|
||||
var len = msg.length;
|
||||
md.messageLength += len;
|
||||
len = [(len / 0x100000000) >>> 0, len >>> 0];
|
||||
for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
|
||||
md.fullMessageLength[i] += len[1];
|
||||
len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
|
||||
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
|
||||
len[0] = (len[1] / 0x100000000) >>> 0;
|
||||
}
|
||||
|
||||
// add bytes to input buffer
|
||||
_input.putBytes(msg);
|
||||
|
||||
// process bytes
|
||||
_update(_state, _w, _input);
|
||||
|
||||
// compact input buffer every 2K or if empty
|
||||
if(_input.read > 2048 || _input.length() === 0) {
|
||||
_input.compact();
|
||||
}
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
/**
|
||||
* Produces the digest.
|
||||
*
|
||||
* @return a byte buffer containing the digest value.
|
||||
*/
|
||||
md.digest = function() {
|
||||
/* Note: Here we copy the remaining bytes in the input buffer and
|
||||
add the appropriate MD5 padding. Then we do the final update
|
||||
on a copy of the state so that if the user wants to get
|
||||
intermediate digests they can do so. */
|
||||
|
||||
/* Determine the number of bytes that must be added to the message
|
||||
to ensure its length is congruent to 448 mod 512. In other words,
|
||||
the data to be digested must be a multiple of 512 bits (or 128 bytes).
|
||||
This data includes the message, some padding, and the length of the
|
||||
message. Since the length of the message will be encoded as 8 bytes (64
|
||||
bits), that means that the last segment of the data must have 56 bytes
|
||||
(448 bits) of message and padding. Therefore, the length of the message
|
||||
plus the padding must be congruent to 448 mod 512 because
|
||||
512 - 128 = 448.
|
||||
|
||||
In order to fill up the message length it must be filled with
|
||||
padding that begins with 1 bit followed by all 0 bits. Padding
|
||||
must *always* be present, so if the message length is already
|
||||
congruent to 448 mod 512, then 512 padding bits must be added. */
|
||||
|
||||
var finalBlock = forge.util.createBuffer();
|
||||
finalBlock.putBytes(_input.bytes());
|
||||
|
||||
// compute remaining size to be digested (include message length size)
|
||||
var remaining = (
|
||||
md.fullMessageLength[md.fullMessageLength.length - 1] +
|
||||
md.messageLengthSize);
|
||||
|
||||
// add padding for overflow blockSize - overflow
|
||||
// _padding starts with 1 byte with first bit is set (byte value 128), then
|
||||
// there may be up to (blockSize - 1) other pad bytes
|
||||
var overflow = remaining & (md.blockLength - 1);
|
||||
finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
|
||||
|
||||
// serialize message length in bits in little-endian order; since length
|
||||
// is stored in bytes we multiply by 8 and add carry
|
||||
var bits, carry = 0;
|
||||
for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
|
||||
bits = md.fullMessageLength[i] * 8 + carry;
|
||||
carry = (bits / 0x100000000) >>> 0;
|
||||
finalBlock.putInt32Le(bits >>> 0);
|
||||
}
|
||||
|
||||
var s2 = {
|
||||
h0: _state.h0,
|
||||
h1: _state.h1,
|
||||
h2: _state.h2,
|
||||
h3: _state.h3
|
||||
};
|
||||
_update(s2, _w, finalBlock);
|
||||
var rval = forge.util.createBuffer();
|
||||
rval.putInt32Le(s2.h0);
|
||||
rval.putInt32Le(s2.h1);
|
||||
rval.putInt32Le(s2.h2);
|
||||
rval.putInt32Le(s2.h3);
|
||||
return rval;
|
||||
};
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
// padding, constant tables for calculating md5
|
||||
var _padding = null;
|
||||
var _g = null;
|
||||
var _r = null;
|
||||
var _k = null;
|
||||
var _initialized = false;
|
||||
|
||||
/**
|
||||
* Initializes the constant tables.
|
||||
*/
|
||||
function _init() {
|
||||
// create padding
|
||||
_padding = String.fromCharCode(128);
|
||||
_padding += forge.util.fillString(String.fromCharCode(0x00), 64);
|
||||
|
||||
// g values
|
||||
_g = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||||
1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
|
||||
5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
|
||||
0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9];
|
||||
|
||||
// rounds table
|
||||
_r = [
|
||||
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21];
|
||||
|
||||
// get the result of abs(sin(i + 1)) as a 32-bit integer
|
||||
_k = new Array(64);
|
||||
for(var i = 0; i < 64; ++i) {
|
||||
_k[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000);
|
||||
}
|
||||
|
||||
// now initialized
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an MD5 state with the given byte buffer.
|
||||
*
|
||||
* @param s the MD5 state to update.
|
||||
* @param w the array to use to store words.
|
||||
* @param bytes the byte buffer to update with.
|
||||
*/
|
||||
function _update(s, w, bytes) {
|
||||
// consume 512 bit (64 byte) chunks
|
||||
var t, a, b, c, d, f, r, i;
|
||||
var len = bytes.length();
|
||||
while(len >= 64) {
|
||||
// initialize hash value for this chunk
|
||||
a = s.h0;
|
||||
b = s.h1;
|
||||
c = s.h2;
|
||||
d = s.h3;
|
||||
|
||||
// round 1
|
||||
for(i = 0; i < 16; ++i) {
|
||||
w[i] = bytes.getInt32Le();
|
||||
f = d ^ (b & (c ^ d));
|
||||
t = (a + f + _k[i] + w[i]);
|
||||
r = _r[i];
|
||||
a = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b += (t << r) | (t >>> (32 - r));
|
||||
}
|
||||
// round 2
|
||||
for(; i < 32; ++i) {
|
||||
f = c ^ (d & (b ^ c));
|
||||
t = (a + f + _k[i] + w[_g[i]]);
|
||||
r = _r[i];
|
||||
a = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b += (t << r) | (t >>> (32 - r));
|
||||
}
|
||||
// round 3
|
||||
for(; i < 48; ++i) {
|
||||
f = b ^ c ^ d;
|
||||
t = (a + f + _k[i] + w[_g[i]]);
|
||||
r = _r[i];
|
||||
a = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b += (t << r) | (t >>> (32 - r));
|
||||
}
|
||||
// round 4
|
||||
for(; i < 64; ++i) {
|
||||
f = c ^ (b | ~d);
|
||||
t = (a + f + _k[i] + w[_g[i]]);
|
||||
r = _r[i];
|
||||
a = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b += (t << r) | (t >>> (32 - r));
|
||||
}
|
||||
|
||||
// update hash state
|
||||
s.h0 = (s.h0 + a) | 0;
|
||||
s.h1 = (s.h1 + b) | 0;
|
||||
s.h2 = (s.h2 + c) | 0;
|
||||
s.h3 = (s.h3 + d) | 0;
|
||||
|
||||
len -= 64;
|
||||
}
|
||||
}
|
12
node_modules/node-forge/lib/mgf.js
generated
vendored
Normal file
12
node_modules/node-forge/lib/mgf.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Node.js module for Forge mask generation functions.
|
||||
*
|
||||
* @author Stefan Siegl
|
||||
*
|
||||
* Copyright 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./mgf1');
|
||||
|
||||
module.exports = forge.mgf = forge.mgf || {};
|
||||
forge.mgf.mgf1 = forge.mgf1;
|
57
node_modules/node-forge/lib/mgf1.js
generated
vendored
Normal file
57
node_modules/node-forge/lib/mgf1.js
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Javascript implementation of mask generation function MGF1.
|
||||
*
|
||||
* @author Stefan Siegl
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
* Copyright (c) 2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
forge.mgf = forge.mgf || {};
|
||||
var mgf1 = module.exports = forge.mgf.mgf1 = forge.mgf1 = forge.mgf1 || {};
|
||||
|
||||
/**
|
||||
* Creates a MGF1 mask generation function object.
|
||||
*
|
||||
* @param md the message digest API to use (eg: forge.md.sha1.create()).
|
||||
*
|
||||
* @return a mask generation function object.
|
||||
*/
|
||||
mgf1.create = function(md) {
|
||||
var mgf = {
|
||||
/**
|
||||
* Generate mask of specified length.
|
||||
*
|
||||
* @param {String} seed The seed for mask generation.
|
||||
* @param maskLen Number of bytes to generate.
|
||||
* @return {String} The generated mask.
|
||||
*/
|
||||
generate: function(seed, maskLen) {
|
||||
/* 2. Let T be the empty octet string. */
|
||||
var t = new forge.util.ByteBuffer();
|
||||
|
||||
/* 3. For counter from 0 to ceil(maskLen / hLen), do the following: */
|
||||
var len = Math.ceil(maskLen / md.digestLength);
|
||||
for(var i = 0; i < len; i++) {
|
||||
/* a. Convert counter to an octet string C of length 4 octets */
|
||||
var c = new forge.util.ByteBuffer();
|
||||
c.putInt32(i);
|
||||
|
||||
/* b. Concatenate the hash of the seed mgfSeed and C to the octet
|
||||
* string T: */
|
||||
md.start();
|
||||
md.update(seed + c.getBytes());
|
||||
t.putBuffer(md.digest());
|
||||
}
|
||||
|
||||
/* Output the leading maskLen octets of T as the octet string mask. */
|
||||
t.truncate(t.length() - maskLen);
|
||||
return t.getBytes();
|
||||
}
|
||||
};
|
||||
|
||||
return mgf;
|
||||
};
|
161
node_modules/node-forge/lib/oids.js
generated
vendored
Normal file
161
node_modules/node-forge/lib/oids.js
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Object IDs for ASN.1.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
|
||||
forge.pki = forge.pki || {};
|
||||
var oids = module.exports = forge.pki.oids = forge.oids = forge.oids || {};
|
||||
|
||||
// set id to name mapping and name to id mapping
|
||||
function _IN(id, name) {
|
||||
oids[id] = name;
|
||||
oids[name] = id;
|
||||
}
|
||||
// set id to name mapping only
|
||||
function _I_(id, name) {
|
||||
oids[id] = name;
|
||||
}
|
||||
|
||||
// algorithm OIDs
|
||||
_IN('1.2.840.113549.1.1.1', 'rsaEncryption');
|
||||
// Note: md2 & md4 not implemented
|
||||
//_IN('1.2.840.113549.1.1.2', 'md2WithRSAEncryption');
|
||||
//_IN('1.2.840.113549.1.1.3', 'md4WithRSAEncryption');
|
||||
_IN('1.2.840.113549.1.1.4', 'md5WithRSAEncryption');
|
||||
_IN('1.2.840.113549.1.1.5', 'sha1WithRSAEncryption');
|
||||
_IN('1.2.840.113549.1.1.7', 'RSAES-OAEP');
|
||||
_IN('1.2.840.113549.1.1.8', 'mgf1');
|
||||
_IN('1.2.840.113549.1.1.9', 'pSpecified');
|
||||
_IN('1.2.840.113549.1.1.10', 'RSASSA-PSS');
|
||||
_IN('1.2.840.113549.1.1.11', 'sha256WithRSAEncryption');
|
||||
_IN('1.2.840.113549.1.1.12', 'sha384WithRSAEncryption');
|
||||
_IN('1.2.840.113549.1.1.13', 'sha512WithRSAEncryption');
|
||||
|
||||
_IN('1.2.840.10040.4.3', 'dsa-with-sha1');
|
||||
|
||||
_IN('1.3.14.3.2.7', 'desCBC');
|
||||
|
||||
_IN('1.3.14.3.2.26', 'sha1');
|
||||
_IN('2.16.840.1.101.3.4.2.1', 'sha256');
|
||||
_IN('2.16.840.1.101.3.4.2.2', 'sha384');
|
||||
_IN('2.16.840.1.101.3.4.2.3', 'sha512');
|
||||
_IN('1.2.840.113549.2.5', 'md5');
|
||||
|
||||
// pkcs#7 content types
|
||||
_IN('1.2.840.113549.1.7.1', 'data');
|
||||
_IN('1.2.840.113549.1.7.2', 'signedData');
|
||||
_IN('1.2.840.113549.1.7.3', 'envelopedData');
|
||||
_IN('1.2.840.113549.1.7.4', 'signedAndEnvelopedData');
|
||||
_IN('1.2.840.113549.1.7.5', 'digestedData');
|
||||
_IN('1.2.840.113549.1.7.6', 'encryptedData');
|
||||
|
||||
// pkcs#9 oids
|
||||
_IN('1.2.840.113549.1.9.1', 'emailAddress');
|
||||
_IN('1.2.840.113549.1.9.2', 'unstructuredName');
|
||||
_IN('1.2.840.113549.1.9.3', 'contentType');
|
||||
_IN('1.2.840.113549.1.9.4', 'messageDigest');
|
||||
_IN('1.2.840.113549.1.9.5', 'signingTime');
|
||||
_IN('1.2.840.113549.1.9.6', 'counterSignature');
|
||||
_IN('1.2.840.113549.1.9.7', 'challengePassword');
|
||||
_IN('1.2.840.113549.1.9.8', 'unstructuredAddress');
|
||||
_IN('1.2.840.113549.1.9.14', 'extensionRequest');
|
||||
|
||||
_IN('1.2.840.113549.1.9.20', 'friendlyName');
|
||||
_IN('1.2.840.113549.1.9.21', 'localKeyId');
|
||||
_IN('1.2.840.113549.1.9.22.1', 'x509Certificate');
|
||||
|
||||
// pkcs#12 safe bags
|
||||
_IN('1.2.840.113549.1.12.10.1.1', 'keyBag');
|
||||
_IN('1.2.840.113549.1.12.10.1.2', 'pkcs8ShroudedKeyBag');
|
||||
_IN('1.2.840.113549.1.12.10.1.3', 'certBag');
|
||||
_IN('1.2.840.113549.1.12.10.1.4', 'crlBag');
|
||||
_IN('1.2.840.113549.1.12.10.1.5', 'secretBag');
|
||||
_IN('1.2.840.113549.1.12.10.1.6', 'safeContentsBag');
|
||||
|
||||
// password-based-encryption for pkcs#12
|
||||
_IN('1.2.840.113549.1.5.13', 'pkcs5PBES2');
|
||||
_IN('1.2.840.113549.1.5.12', 'pkcs5PBKDF2');
|
||||
|
||||
_IN('1.2.840.113549.1.12.1.1', 'pbeWithSHAAnd128BitRC4');
|
||||
_IN('1.2.840.113549.1.12.1.2', 'pbeWithSHAAnd40BitRC4');
|
||||
_IN('1.2.840.113549.1.12.1.3', 'pbeWithSHAAnd3-KeyTripleDES-CBC');
|
||||
_IN('1.2.840.113549.1.12.1.4', 'pbeWithSHAAnd2-KeyTripleDES-CBC');
|
||||
_IN('1.2.840.113549.1.12.1.5', 'pbeWithSHAAnd128BitRC2-CBC');
|
||||
_IN('1.2.840.113549.1.12.1.6', 'pbewithSHAAnd40BitRC2-CBC');
|
||||
|
||||
// hmac OIDs
|
||||
_IN('1.2.840.113549.2.7', 'hmacWithSHA1');
|
||||
_IN('1.2.840.113549.2.8', 'hmacWithSHA224');
|
||||
_IN('1.2.840.113549.2.9', 'hmacWithSHA256');
|
||||
_IN('1.2.840.113549.2.10', 'hmacWithSHA384');
|
||||
_IN('1.2.840.113549.2.11', 'hmacWithSHA512');
|
||||
|
||||
// symmetric key algorithm oids
|
||||
_IN('1.2.840.113549.3.7', 'des-EDE3-CBC');
|
||||
_IN('2.16.840.1.101.3.4.1.2', 'aes128-CBC');
|
||||
_IN('2.16.840.1.101.3.4.1.22', 'aes192-CBC');
|
||||
_IN('2.16.840.1.101.3.4.1.42', 'aes256-CBC');
|
||||
|
||||
// certificate issuer/subject OIDs
|
||||
_IN('2.5.4.3', 'commonName');
|
||||
_IN('2.5.4.5', 'serialName');
|
||||
_IN('2.5.4.6', 'countryName');
|
||||
_IN('2.5.4.7', 'localityName');
|
||||
_IN('2.5.4.8', 'stateOrProvinceName');
|
||||
_IN('2.5.4.10', 'organizationName');
|
||||
_IN('2.5.4.11', 'organizationalUnitName');
|
||||
|
||||
// X.509 extension OIDs
|
||||
_IN('2.16.840.1.113730.1.1', 'nsCertType');
|
||||
_I_('2.5.29.1', 'authorityKeyIdentifier'); // deprecated, use .35
|
||||
_I_('2.5.29.2', 'keyAttributes'); // obsolete use .37 or .15
|
||||
_I_('2.5.29.3', 'certificatePolicies'); // deprecated, use .32
|
||||
_I_('2.5.29.4', 'keyUsageRestriction'); // obsolete use .37 or .15
|
||||
_I_('2.5.29.5', 'policyMapping'); // deprecated use .33
|
||||
_I_('2.5.29.6', 'subtreesConstraint'); // obsolete use .30
|
||||
_I_('2.5.29.7', 'subjectAltName'); // deprecated use .17
|
||||
_I_('2.5.29.8', 'issuerAltName'); // deprecated use .18
|
||||
_I_('2.5.29.9', 'subjectDirectoryAttributes');
|
||||
_I_('2.5.29.10', 'basicConstraints'); // deprecated use .19
|
||||
_I_('2.5.29.11', 'nameConstraints'); // deprecated use .30
|
||||
_I_('2.5.29.12', 'policyConstraints'); // deprecated use .36
|
||||
_I_('2.5.29.13', 'basicConstraints'); // deprecated use .19
|
||||
_IN('2.5.29.14', 'subjectKeyIdentifier');
|
||||
_IN('2.5.29.15', 'keyUsage');
|
||||
_I_('2.5.29.16', 'privateKeyUsagePeriod');
|
||||
_IN('2.5.29.17', 'subjectAltName');
|
||||
_IN('2.5.29.18', 'issuerAltName');
|
||||
_IN('2.5.29.19', 'basicConstraints');
|
||||
_I_('2.5.29.20', 'cRLNumber');
|
||||
_I_('2.5.29.21', 'cRLReason');
|
||||
_I_('2.5.29.22', 'expirationDate');
|
||||
_I_('2.5.29.23', 'instructionCode');
|
||||
_I_('2.5.29.24', 'invalidityDate');
|
||||
_I_('2.5.29.25', 'cRLDistributionPoints'); // deprecated use .31
|
||||
_I_('2.5.29.26', 'issuingDistributionPoint'); // deprecated use .28
|
||||
_I_('2.5.29.27', 'deltaCRLIndicator');
|
||||
_I_('2.5.29.28', 'issuingDistributionPoint');
|
||||
_I_('2.5.29.29', 'certificateIssuer');
|
||||
_I_('2.5.29.30', 'nameConstraints');
|
||||
_IN('2.5.29.31', 'cRLDistributionPoints');
|
||||
_IN('2.5.29.32', 'certificatePolicies');
|
||||
_I_('2.5.29.33', 'policyMappings');
|
||||
_I_('2.5.29.34', 'policyConstraints'); // deprecated use .36
|
||||
_IN('2.5.29.35', 'authorityKeyIdentifier');
|
||||
_I_('2.5.29.36', 'policyConstraints');
|
||||
_IN('2.5.29.37', 'extKeyUsage');
|
||||
_I_('2.5.29.46', 'freshestCRL');
|
||||
_I_('2.5.29.54', 'inhibitAnyPolicy');
|
||||
|
||||
// extKeyUsage purposes
|
||||
_IN('1.3.6.1.4.1.11129.2.4.2', 'timestampList');
|
||||
_IN('1.3.6.1.5.5.7.1.1', 'authorityInfoAccess');
|
||||
_IN('1.3.6.1.5.5.7.3.1', 'serverAuth');
|
||||
_IN('1.3.6.1.5.5.7.3.2', 'clientAuth');
|
||||
_IN('1.3.6.1.5.5.7.3.3', 'codeSigning');
|
||||
_IN('1.3.6.1.5.5.7.3.4', 'emailProtection');
|
||||
_IN('1.3.6.1.5.5.7.3.8', 'timeStamping');
|
1023
node_modules/node-forge/lib/pbe.js
generated
vendored
Normal file
1023
node_modules/node-forge/lib/pbe.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
211
node_modules/node-forge/lib/pbkdf2.js
generated
vendored
Normal file
211
node_modules/node-forge/lib/pbkdf2.js
generated
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
/**
|
||||
* Password-Based Key-Derivation Function #2 implementation.
|
||||
*
|
||||
* See RFC 2898 for details.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./hmac');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
var pkcs5 = forge.pkcs5 = forge.pkcs5 || {};
|
||||
|
||||
var crypto;
|
||||
if(forge.util.isNodejs && !forge.options.usePureJavaScript) {
|
||||
crypto = require('crypto');
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives a key from a password.
|
||||
*
|
||||
* @param p the password as a binary-encoded string of bytes.
|
||||
* @param s the salt as a binary-encoded string of bytes.
|
||||
* @param c the iteration count, a positive integer.
|
||||
* @param dkLen the intended length, in bytes, of the derived key,
|
||||
* (max: 2^32 - 1) * hash length of the PRF.
|
||||
* @param [md] the message digest (or algorithm identifier as a string) to use
|
||||
* in the PRF, defaults to SHA-1.
|
||||
* @param [callback(err, key)] presence triggers asynchronous version, called
|
||||
* once the operation completes.
|
||||
*
|
||||
* @return the derived key, as a binary-encoded string of bytes, for the
|
||||
* synchronous version (if no callback is specified).
|
||||
*/
|
||||
module.exports = forge.pbkdf2 = pkcs5.pbkdf2 = function(
|
||||
p, s, c, dkLen, md, callback) {
|
||||
if(typeof md === 'function') {
|
||||
callback = md;
|
||||
md = null;
|
||||
}
|
||||
|
||||
// use native implementation if possible and not disabled, note that
|
||||
// some node versions only support SHA-1, others allow digest to be changed
|
||||
if(forge.util.isNodejs && !forge.options.usePureJavaScript &&
|
||||
crypto.pbkdf2 && (md === null || typeof md !== 'object') &&
|
||||
(crypto.pbkdf2Sync.length > 4 || (!md || md === 'sha1'))) {
|
||||
if(typeof md !== 'string') {
|
||||
// default prf to SHA-1
|
||||
md = 'sha1';
|
||||
}
|
||||
p = new Buffer(p, 'binary');
|
||||
s = new Buffer(s, 'binary');
|
||||
if(!callback) {
|
||||
if(crypto.pbkdf2Sync.length === 4) {
|
||||
return crypto.pbkdf2Sync(p, s, c, dkLen).toString('binary');
|
||||
}
|
||||
return crypto.pbkdf2Sync(p, s, c, dkLen, md).toString('binary');
|
||||
}
|
||||
if(crypto.pbkdf2Sync.length === 4) {
|
||||
return crypto.pbkdf2(p, s, c, dkLen, function(err, key) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, key.toString('binary'));
|
||||
});
|
||||
}
|
||||
return crypto.pbkdf2(p, s, c, dkLen, md, function(err, key) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, key.toString('binary'));
|
||||
});
|
||||
}
|
||||
|
||||
if(typeof md === 'undefined' || md === null) {
|
||||
// default prf to SHA-1
|
||||
md = 'sha1';
|
||||
}
|
||||
if(typeof md === 'string') {
|
||||
if(!(md in forge.md.algorithms)) {
|
||||
throw new Error('Unknown hash algorithm: ' + md);
|
||||
}
|
||||
md = forge.md[md].create();
|
||||
}
|
||||
|
||||
var hLen = md.digestLength;
|
||||
|
||||
/* 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
|
||||
stop. */
|
||||
if(dkLen > (0xFFFFFFFF * hLen)) {
|
||||
var err = new Error('Derived key is too long.');
|
||||
if(callback) {
|
||||
return callback(err);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
/* 2. Let len be the number of hLen-octet blocks in the derived key,
|
||||
rounding up, and let r be the number of octets in the last
|
||||
block:
|
||||
|
||||
len = CEIL(dkLen / hLen),
|
||||
r = dkLen - (len - 1) * hLen. */
|
||||
var len = Math.ceil(dkLen / hLen);
|
||||
var r = dkLen - (len - 1) * hLen;
|
||||
|
||||
/* 3. For each block of the derived key apply the function F defined
|
||||
below to the password P, the salt S, the iteration count c, and
|
||||
the block index to compute the block:
|
||||
|
||||
T_1 = F(P, S, c, 1),
|
||||
T_2 = F(P, S, c, 2),
|
||||
...
|
||||
T_len = F(P, S, c, len),
|
||||
|
||||
where the function F is defined as the exclusive-or sum of the
|
||||
first c iterates of the underlying pseudorandom function PRF
|
||||
applied to the password P and the concatenation of the salt S
|
||||
and the block index i:
|
||||
|
||||
F(P, S, c, i) = u_1 XOR u_2 XOR ... XOR u_c
|
||||
|
||||
where
|
||||
|
||||
u_1 = PRF(P, S || INT(i)),
|
||||
u_2 = PRF(P, u_1),
|
||||
...
|
||||
u_c = PRF(P, u_{c-1}).
|
||||
|
||||
Here, INT(i) is a four-octet encoding of the integer i, most
|
||||
significant octet first. */
|
||||
var prf = forge.hmac.create();
|
||||
prf.start(md, p);
|
||||
var dk = '';
|
||||
var xor, u_c, u_c1;
|
||||
|
||||
// sync version
|
||||
if(!callback) {
|
||||
for(var i = 1; i <= len; ++i) {
|
||||
// PRF(P, S || INT(i)) (first iteration)
|
||||
prf.start(null, null);
|
||||
prf.update(s);
|
||||
prf.update(forge.util.int32ToBytes(i));
|
||||
xor = u_c1 = prf.digest().getBytes();
|
||||
|
||||
// PRF(P, u_{c-1}) (other iterations)
|
||||
for(var j = 2; j <= c; ++j) {
|
||||
prf.start(null, null);
|
||||
prf.update(u_c1);
|
||||
u_c = prf.digest().getBytes();
|
||||
// F(p, s, c, i)
|
||||
xor = forge.util.xorBytes(xor, u_c, hLen);
|
||||
u_c1 = u_c;
|
||||
}
|
||||
|
||||
/* 4. Concatenate the blocks and extract the first dkLen octets to
|
||||
produce a derived key DK:
|
||||
|
||||
DK = T_1 || T_2 || ... || T_len<0..r-1> */
|
||||
dk += (i < len) ? xor : xor.substr(0, r);
|
||||
}
|
||||
/* 5. Output the derived key DK. */
|
||||
return dk;
|
||||
}
|
||||
|
||||
// async version
|
||||
var i = 1, j;
|
||||
function outer() {
|
||||
if(i > len) {
|
||||
// done
|
||||
return callback(null, dk);
|
||||
}
|
||||
|
||||
// PRF(P, S || INT(i)) (first iteration)
|
||||
prf.start(null, null);
|
||||
prf.update(s);
|
||||
prf.update(forge.util.int32ToBytes(i));
|
||||
xor = u_c1 = prf.digest().getBytes();
|
||||
|
||||
// PRF(P, u_{c-1}) (other iterations)
|
||||
j = 2;
|
||||
inner();
|
||||
}
|
||||
|
||||
function inner() {
|
||||
if(j <= c) {
|
||||
prf.start(null, null);
|
||||
prf.update(u_c1);
|
||||
u_c = prf.digest().getBytes();
|
||||
// F(p, s, c, i)
|
||||
xor = forge.util.xorBytes(xor, u_c, hLen);
|
||||
u_c1 = u_c;
|
||||
++j;
|
||||
return forge.util.setImmediate(inner);
|
||||
}
|
||||
|
||||
/* 4. Concatenate the blocks and extract the first dkLen octets to
|
||||
produce a derived key DK:
|
||||
|
||||
DK = T_1 || T_2 || ... || T_len<0..r-1> */
|
||||
dk += (i < len) ? xor : xor.substr(0, r);
|
||||
|
||||
++i;
|
||||
outer();
|
||||
}
|
||||
|
||||
outer();
|
||||
};
|
230
node_modules/node-forge/lib/pem.js
generated
vendored
Normal file
230
node_modules/node-forge/lib/pem.js
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
/**
|
||||
* Javascript implementation of basic PEM (Privacy Enhanced Mail) algorithms.
|
||||
*
|
||||
* See: RFC 1421.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2013-2014 Digital Bazaar, Inc.
|
||||
*
|
||||
* A Forge PEM object has the following fields:
|
||||
*
|
||||
* type: identifies the type of message (eg: "RSA PRIVATE KEY").
|
||||
*
|
||||
* procType: identifies the type of processing performed on the message,
|
||||
* it has two subfields: version and type, eg: 4,ENCRYPTED.
|
||||
*
|
||||
* contentDomain: identifies the type of content in the message, typically
|
||||
* only uses the value: "RFC822".
|
||||
*
|
||||
* dekInfo: identifies the message encryption algorithm and mode and includes
|
||||
* any parameters for the algorithm, it has two subfields: algorithm and
|
||||
* parameters, eg: DES-CBC,F8143EDE5960C597.
|
||||
*
|
||||
* headers: contains all other PEM encapsulated headers -- where order is
|
||||
* significant (for pairing data like recipient ID + key info).
|
||||
*
|
||||
* body: the binary-encoded body.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
// shortcut for pem API
|
||||
var pem = module.exports = forge.pem = forge.pem || {};
|
||||
|
||||
/**
|
||||
* Encodes (serializes) the given PEM object.
|
||||
*
|
||||
* @param msg the PEM message object to encode.
|
||||
* @param options the options to use:
|
||||
* maxline the maximum characters per line for the body, (default: 64).
|
||||
*
|
||||
* @return the PEM-formatted string.
|
||||
*/
|
||||
pem.encode = function(msg, options) {
|
||||
options = options || {};
|
||||
var rval = '-----BEGIN ' + msg.type + '-----\r\n';
|
||||
|
||||
// encode special headers
|
||||
var header;
|
||||
if(msg.procType) {
|
||||
header = {
|
||||
name: 'Proc-Type',
|
||||
values: [String(msg.procType.version), msg.procType.type]
|
||||
};
|
||||
rval += foldHeader(header);
|
||||
}
|
||||
if(msg.contentDomain) {
|
||||
header = {name: 'Content-Domain', values: [msg.contentDomain]};
|
||||
rval += foldHeader(header);
|
||||
}
|
||||
if(msg.dekInfo) {
|
||||
header = {name: 'DEK-Info', values: [msg.dekInfo.algorithm]};
|
||||
if(msg.dekInfo.parameters) {
|
||||
header.values.push(msg.dekInfo.parameters);
|
||||
}
|
||||
rval += foldHeader(header);
|
||||
}
|
||||
|
||||
if(msg.headers) {
|
||||
// encode all other headers
|
||||
for(var i = 0; i < msg.headers.length; ++i) {
|
||||
rval += foldHeader(msg.headers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// terminate header
|
||||
if(msg.procType) {
|
||||
rval += '\r\n';
|
||||
}
|
||||
|
||||
// add body
|
||||
rval += forge.util.encode64(msg.body, options.maxline || 64) + '\r\n';
|
||||
|
||||
rval += '-----END ' + msg.type + '-----\r\n';
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decodes (deserializes) all PEM messages found in the given string.
|
||||
*
|
||||
* @param str the PEM-formatted string to decode.
|
||||
*
|
||||
* @return the PEM message objects in an array.
|
||||
*/
|
||||
pem.decode = function(str) {
|
||||
var rval = [];
|
||||
|
||||
// split string into PEM messages (be lenient w/EOF on BEGIN line)
|
||||
var rMessage = /\s*-----BEGIN ([A-Z0-9- ]+)-----\r?\n?([\x21-\x7e\s]+?(?:\r?\n\r?\n))?([:A-Za-z0-9+\/=\s]+?)-----END \1-----/g;
|
||||
var rHeader = /([\x21-\x7e]+):\s*([\x21-\x7e\s^:]+)/;
|
||||
var rCRLF = /\r?\n/;
|
||||
var match;
|
||||
while(true) {
|
||||
match = rMessage.exec(str);
|
||||
if(!match) {
|
||||
break;
|
||||
}
|
||||
|
||||
var msg = {
|
||||
type: match[1],
|
||||
procType: null,
|
||||
contentDomain: null,
|
||||
dekInfo: null,
|
||||
headers: [],
|
||||
body: forge.util.decode64(match[3])
|
||||
};
|
||||
rval.push(msg);
|
||||
|
||||
// no headers
|
||||
if(!match[2]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// parse headers
|
||||
var lines = match[2].split(rCRLF);
|
||||
var li = 0;
|
||||
while(match && li < lines.length) {
|
||||
// get line, trim any rhs whitespace
|
||||
var line = lines[li].replace(/\s+$/, '');
|
||||
|
||||
// RFC2822 unfold any following folded lines
|
||||
for(var nl = li + 1; nl < lines.length; ++nl) {
|
||||
var next = lines[nl];
|
||||
if(!/\s/.test(next[0])) {
|
||||
break;
|
||||
}
|
||||
line += next;
|
||||
li = nl;
|
||||
}
|
||||
|
||||
// parse header
|
||||
match = line.match(rHeader);
|
||||
if(match) {
|
||||
var header = {name: match[1], values: []};
|
||||
var values = match[2].split(',');
|
||||
for(var vi = 0; vi < values.length; ++vi) {
|
||||
header.values.push(ltrim(values[vi]));
|
||||
}
|
||||
|
||||
// Proc-Type must be the first header
|
||||
if(!msg.procType) {
|
||||
if(header.name !== 'Proc-Type') {
|
||||
throw new Error('Invalid PEM formatted message. The first ' +
|
||||
'encapsulated header must be "Proc-Type".');
|
||||
} else if(header.values.length !== 2) {
|
||||
throw new Error('Invalid PEM formatted message. The "Proc-Type" ' +
|
||||
'header must have two subfields.');
|
||||
}
|
||||
msg.procType = {version: values[0], type: values[1]};
|
||||
} else if(!msg.contentDomain && header.name === 'Content-Domain') {
|
||||
// special-case Content-Domain
|
||||
msg.contentDomain = values[0] || '';
|
||||
} else if(!msg.dekInfo && header.name === 'DEK-Info') {
|
||||
// special-case DEK-Info
|
||||
if(header.values.length === 0) {
|
||||
throw new Error('Invalid PEM formatted message. The "DEK-Info" ' +
|
||||
'header must have at least one subfield.');
|
||||
}
|
||||
msg.dekInfo = {algorithm: values[0], parameters: values[1] || null};
|
||||
} else {
|
||||
msg.headers.push(header);
|
||||
}
|
||||
}
|
||||
|
||||
++li;
|
||||
}
|
||||
|
||||
if(msg.procType === 'ENCRYPTED' && !msg.dekInfo) {
|
||||
throw new Error('Invalid PEM formatted message. The "DEK-Info" ' +
|
||||
'header must be present if "Proc-Type" is "ENCRYPTED".');
|
||||
}
|
||||
}
|
||||
|
||||
if(rval.length === 0) {
|
||||
throw new Error('Invalid PEM formatted message.');
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
function foldHeader(header) {
|
||||
var rval = header.name + ': ';
|
||||
|
||||
// ensure values with CRLF are folded
|
||||
var values = [];
|
||||
var insertSpace = function(match, $1) {
|
||||
return ' ' + $1;
|
||||
};
|
||||
for(var i = 0; i < header.values.length; ++i) {
|
||||
values.push(header.values[i].replace(/^(\S+\r\n)/, insertSpace));
|
||||
}
|
||||
rval += values.join(',') + '\r\n';
|
||||
|
||||
// do folding
|
||||
var length = 0;
|
||||
var candidate = -1;
|
||||
for(var i = 0; i < rval.length; ++i, ++length) {
|
||||
if(length > 65 && candidate !== -1) {
|
||||
var insert = rval[candidate];
|
||||
if(insert === ',') {
|
||||
++candidate;
|
||||
rval = rval.substr(0, candidate) + '\r\n ' + rval.substr(candidate);
|
||||
} else {
|
||||
rval = rval.substr(0, candidate) +
|
||||
'\r\n' + insert + rval.substr(candidate + 1);
|
||||
}
|
||||
length = (i - candidate - 1);
|
||||
candidate = -1;
|
||||
++i;
|
||||
} else if(rval[i] === ' ' || rval[i] === '\t' || rval[i] === ',') {
|
||||
candidate = i;
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
function ltrim(str) {
|
||||
return str.replace(/^\s+/, '');
|
||||
}
|
276
node_modules/node-forge/lib/pkcs1.js
generated
vendored
Normal file
276
node_modules/node-forge/lib/pkcs1.js
generated
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
/**
|
||||
* Partial implementation of PKCS#1 v2.2: RSA-OEAP
|
||||
*
|
||||
* Modified but based on the following MIT and BSD licensed code:
|
||||
*
|
||||
* https://github.com/kjur/jsjws/blob/master/rsa.js:
|
||||
*
|
||||
* The 'jsjws'(JSON Web Signature JavaScript Library) License
|
||||
*
|
||||
* Copyright (c) 2012 Kenji Urushima
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* http://webrsa.cvs.sourceforge.net/viewvc/webrsa/Client/RSAES-OAEP.js?content-type=text%2Fplain:
|
||||
*
|
||||
* RSAES-OAEP.js
|
||||
* $Id: RSAES-OAEP.js,v 1.1.1.1 2003/03/19 15:37:20 ellispritchard Exp $
|
||||
* JavaScript Implementation of PKCS #1 v2.1 RSA CRYPTOGRAPHY STANDARD (RSA Laboratories, June 14, 2002)
|
||||
* Copyright (C) Ellis Pritchard, Guardian Unlimited 2003.
|
||||
* Contact: ellis@nukinetics.com
|
||||
* Distributed under the BSD License.
|
||||
*
|
||||
* Official documentation: http://www.rsa.com/rsalabs/node.asp?id=2125
|
||||
*
|
||||
* @author Evan Jones (http://evanjones.ca/)
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2013-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
require('./random');
|
||||
require('./sha1');
|
||||
|
||||
// shortcut for PKCS#1 API
|
||||
var pkcs1 = module.exports = forge.pkcs1 = forge.pkcs1 || {};
|
||||
|
||||
/**
|
||||
* Encode the given RSAES-OAEP message (M) using key, with optional label (L)
|
||||
* and seed.
|
||||
*
|
||||
* This method does not perform RSA encryption, it only encodes the message
|
||||
* using RSAES-OAEP.
|
||||
*
|
||||
* @param key the RSA key to use.
|
||||
* @param message the message to encode.
|
||||
* @param options the options to use:
|
||||
* label an optional label to use.
|
||||
* seed the seed to use.
|
||||
* md the message digest object to use, undefined for SHA-1.
|
||||
* mgf1 optional mgf1 parameters:
|
||||
* md the message digest object to use for MGF1.
|
||||
*
|
||||
* @return the encoded message bytes.
|
||||
*/
|
||||
pkcs1.encode_rsa_oaep = function(key, message, options) {
|
||||
// parse arguments
|
||||
var label;
|
||||
var seed;
|
||||
var md;
|
||||
var mgf1Md;
|
||||
// legacy args (label, seed, md)
|
||||
if(typeof options === 'string') {
|
||||
label = options;
|
||||
seed = arguments[3] || undefined;
|
||||
md = arguments[4] || undefined;
|
||||
} else if(options) {
|
||||
label = options.label || undefined;
|
||||
seed = options.seed || undefined;
|
||||
md = options.md || undefined;
|
||||
if(options.mgf1 && options.mgf1.md) {
|
||||
mgf1Md = options.mgf1.md;
|
||||
}
|
||||
}
|
||||
|
||||
// default OAEP to SHA-1 message digest
|
||||
if(!md) {
|
||||
md = forge.md.sha1.create();
|
||||
} else {
|
||||
md.start();
|
||||
}
|
||||
|
||||
// default MGF-1 to same as OAEP
|
||||
if(!mgf1Md) {
|
||||
mgf1Md = md;
|
||||
}
|
||||
|
||||
// compute length in bytes and check output
|
||||
var keyLength = Math.ceil(key.n.bitLength() / 8);
|
||||
var maxLength = keyLength - 2 * md.digestLength - 2;
|
||||
if(message.length > maxLength) {
|
||||
var error = new Error('RSAES-OAEP input message length is too long.');
|
||||
error.length = message.length;
|
||||
error.maxLength = maxLength;
|
||||
throw error;
|
||||
}
|
||||
|
||||
if(!label) {
|
||||
label = '';
|
||||
}
|
||||
md.update(label, 'raw');
|
||||
var lHash = md.digest();
|
||||
|
||||
var PS = '';
|
||||
var PS_length = maxLength - message.length;
|
||||
for (var i = 0; i < PS_length; i++) {
|
||||
PS += '\x00';
|
||||
}
|
||||
|
||||
var DB = lHash.getBytes() + PS + '\x01' + message;
|
||||
|
||||
if(!seed) {
|
||||
seed = forge.random.getBytes(md.digestLength);
|
||||
} else if(seed.length !== md.digestLength) {
|
||||
var error = new Error('Invalid RSAES-OAEP seed. The seed length must ' +
|
||||
'match the digest length.');
|
||||
error.seedLength = seed.length;
|
||||
error.digestLength = md.digestLength;
|
||||
throw error;
|
||||
}
|
||||
|
||||
var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md);
|
||||
var maskedDB = forge.util.xorBytes(DB, dbMask, DB.length);
|
||||
|
||||
var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md);
|
||||
var maskedSeed = forge.util.xorBytes(seed, seedMask, seed.length);
|
||||
|
||||
// return encoded message
|
||||
return '\x00' + maskedSeed + maskedDB;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decode the given RSAES-OAEP encoded message (EM) using key, with optional
|
||||
* label (L).
|
||||
*
|
||||
* This method does not perform RSA decryption, it only decodes the message
|
||||
* using RSAES-OAEP.
|
||||
*
|
||||
* @param key the RSA key to use.
|
||||
* @param em the encoded message to decode.
|
||||
* @param options the options to use:
|
||||
* label an optional label to use.
|
||||
* md the message digest object to use for OAEP, undefined for SHA-1.
|
||||
* mgf1 optional mgf1 parameters:
|
||||
* md the message digest object to use for MGF1.
|
||||
*
|
||||
* @return the decoded message bytes.
|
||||
*/
|
||||
pkcs1.decode_rsa_oaep = function(key, em, options) {
|
||||
// parse args
|
||||
var label;
|
||||
var md;
|
||||
var mgf1Md;
|
||||
// legacy args
|
||||
if(typeof options === 'string') {
|
||||
label = options;
|
||||
md = arguments[3] || undefined;
|
||||
} else if(options) {
|
||||
label = options.label || undefined;
|
||||
md = options.md || undefined;
|
||||
if(options.mgf1 && options.mgf1.md) {
|
||||
mgf1Md = options.mgf1.md;
|
||||
}
|
||||
}
|
||||
|
||||
// compute length in bytes
|
||||
var keyLength = Math.ceil(key.n.bitLength() / 8);
|
||||
|
||||
if(em.length !== keyLength) {
|
||||
var error = new Error('RSAES-OAEP encoded message length is invalid.');
|
||||
error.length = em.length;
|
||||
error.expectedLength = keyLength;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// default OAEP to SHA-1 message digest
|
||||
if(md === undefined) {
|
||||
md = forge.md.sha1.create();
|
||||
} else {
|
||||
md.start();
|
||||
}
|
||||
|
||||
// default MGF-1 to same as OAEP
|
||||
if(!mgf1Md) {
|
||||
mgf1Md = md;
|
||||
}
|
||||
|
||||
if(keyLength < 2 * md.digestLength + 2) {
|
||||
throw new Error('RSAES-OAEP key is too short for the hash function.');
|
||||
}
|
||||
|
||||
if(!label) {
|
||||
label = '';
|
||||
}
|
||||
md.update(label, 'raw');
|
||||
var lHash = md.digest().getBytes();
|
||||
|
||||
// split the message into its parts
|
||||
var y = em.charAt(0);
|
||||
var maskedSeed = em.substring(1, md.digestLength + 1);
|
||||
var maskedDB = em.substring(1 + md.digestLength);
|
||||
|
||||
var seedMask = rsa_mgf1(maskedDB, md.digestLength, mgf1Md);
|
||||
var seed = forge.util.xorBytes(maskedSeed, seedMask, maskedSeed.length);
|
||||
|
||||
var dbMask = rsa_mgf1(seed, keyLength - md.digestLength - 1, mgf1Md);
|
||||
var db = forge.util.xorBytes(maskedDB, dbMask, maskedDB.length);
|
||||
|
||||
var lHashPrime = db.substring(0, md.digestLength);
|
||||
|
||||
// constant time check that all values match what is expected
|
||||
var error = (y !== '\x00');
|
||||
|
||||
// constant time check lHash vs lHashPrime
|
||||
for(var i = 0; i < md.digestLength; ++i) {
|
||||
error |= (lHash.charAt(i) !== lHashPrime.charAt(i));
|
||||
}
|
||||
|
||||
// "constant time" find the 0x1 byte separating the padding (zeros) from the
|
||||
// message
|
||||
// TODO: It must be possible to do this in a better/smarter way?
|
||||
var in_ps = 1;
|
||||
var index = md.digestLength;
|
||||
for(var j = md.digestLength; j < db.length; j++) {
|
||||
var code = db.charCodeAt(j);
|
||||
|
||||
var is_0 = (code & 0x1) ^ 0x1;
|
||||
|
||||
// non-zero if not 0 or 1 in the ps section
|
||||
var error_mask = in_ps ? 0xfffe : 0x0000;
|
||||
error |= (code & error_mask);
|
||||
|
||||
// latch in_ps to zero after we find 0x1
|
||||
in_ps = in_ps & is_0;
|
||||
index += in_ps;
|
||||
}
|
||||
|
||||
if(error || db.charCodeAt(index) !== 0x1) {
|
||||
throw new Error('Invalid RSAES-OAEP padding.');
|
||||
}
|
||||
|
||||
return db.substring(index + 1);
|
||||
};
|
||||
|
||||
function rsa_mgf1(seed, maskLength, hash) {
|
||||
// default to SHA-1 message digest
|
||||
if(!hash) {
|
||||
hash = forge.md.sha1.create();
|
||||
}
|
||||
var t = '';
|
||||
var count = Math.ceil(maskLength / hash.digestLength);
|
||||
for(var i = 0; i < count; ++i) {
|
||||
var c = String.fromCharCode(
|
||||
(i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
|
||||
hash.start();
|
||||
hash.update(seed + c);
|
||||
t += hash.digest().getBytes();
|
||||
}
|
||||
return t.substring(0, maskLength);
|
||||
}
|
1074
node_modules/node-forge/lib/pkcs12.js
generated
vendored
Normal file
1074
node_modules/node-forge/lib/pkcs12.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1243
node_modules/node-forge/lib/pkcs7.js
generated
vendored
Normal file
1243
node_modules/node-forge/lib/pkcs7.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
409
node_modules/node-forge/lib/pkcs7asn1.js
generated
vendored
Normal file
409
node_modules/node-forge/lib/pkcs7asn1.js
generated
vendored
Normal file
@ -0,0 +1,409 @@
|
||||
/**
|
||||
* Javascript implementation of ASN.1 validators for PKCS#7 v1.5.
|
||||
*
|
||||
* @author Dave Longley
|
||||
* @author Stefan Siegl
|
||||
*
|
||||
* Copyright (c) 2012-2015 Digital Bazaar, Inc.
|
||||
* Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
*
|
||||
* The ASN.1 representation of PKCS#7 is as follows
|
||||
* (see RFC #2315 for details, http://www.ietf.org/rfc/rfc2315.txt):
|
||||
*
|
||||
* A PKCS#7 message consists of a ContentInfo on root level, which may
|
||||
* contain any number of further ContentInfo nested into it.
|
||||
*
|
||||
* ContentInfo ::= SEQUENCE {
|
||||
* contentType ContentType,
|
||||
* content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
|
||||
* }
|
||||
*
|
||||
* ContentType ::= OBJECT IDENTIFIER
|
||||
*
|
||||
* EnvelopedData ::= SEQUENCE {
|
||||
* version Version,
|
||||
* recipientInfos RecipientInfos,
|
||||
* encryptedContentInfo EncryptedContentInfo
|
||||
* }
|
||||
*
|
||||
* EncryptedData ::= SEQUENCE {
|
||||
* version Version,
|
||||
* encryptedContentInfo EncryptedContentInfo
|
||||
* }
|
||||
*
|
||||
* id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2)
|
||||
* us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 }
|
||||
*
|
||||
* SignedData ::= SEQUENCE {
|
||||
* version INTEGER,
|
||||
* digestAlgorithms DigestAlgorithmIdentifiers,
|
||||
* contentInfo ContentInfo,
|
||||
* certificates [0] IMPLICIT Certificates OPTIONAL,
|
||||
* crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
|
||||
* signerInfos SignerInfos
|
||||
* }
|
||||
*
|
||||
* SignerInfos ::= SET OF SignerInfo
|
||||
*
|
||||
* SignerInfo ::= SEQUENCE {
|
||||
* version Version,
|
||||
* issuerAndSerialNumber IssuerAndSerialNumber,
|
||||
* digestAlgorithm DigestAlgorithmIdentifier,
|
||||
* authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
|
||||
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
|
||||
* encryptedDigest EncryptedDigest,
|
||||
* unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
|
||||
* }
|
||||
*
|
||||
* EncryptedDigest ::= OCTET STRING
|
||||
*
|
||||
* Attributes ::= SET OF Attribute
|
||||
*
|
||||
* Attribute ::= SEQUENCE {
|
||||
* attrType OBJECT IDENTIFIER,
|
||||
* attrValues SET OF AttributeValue
|
||||
* }
|
||||
*
|
||||
* AttributeValue ::= ANY
|
||||
*
|
||||
* Version ::= INTEGER
|
||||
*
|
||||
* RecipientInfos ::= SET OF RecipientInfo
|
||||
*
|
||||
* EncryptedContentInfo ::= SEQUENCE {
|
||||
* contentType ContentType,
|
||||
* contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
|
||||
* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
|
||||
* }
|
||||
*
|
||||
* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||
*
|
||||
* The AlgorithmIdentifier contains an Object Identifier (OID) and parameters
|
||||
* for the algorithm, if any. In the case of AES and DES3, there is only one,
|
||||
* the IV.
|
||||
*
|
||||
* AlgorithmIdentifer ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* EncryptedContent ::= OCTET STRING
|
||||
*
|
||||
* RecipientInfo ::= SEQUENCE {
|
||||
* version Version,
|
||||
* issuerAndSerialNumber IssuerAndSerialNumber,
|
||||
* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
|
||||
* encryptedKey EncryptedKey
|
||||
* }
|
||||
*
|
||||
* IssuerAndSerialNumber ::= SEQUENCE {
|
||||
* issuer Name,
|
||||
* serialNumber CertificateSerialNumber
|
||||
* }
|
||||
*
|
||||
* CertificateSerialNumber ::= INTEGER
|
||||
*
|
||||
* KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
|
||||
*
|
||||
* EncryptedKey ::= OCTET STRING
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./asn1');
|
||||
require('./util');
|
||||
|
||||
// shortcut for ASN.1 API
|
||||
var asn1 = forge.asn1;
|
||||
|
||||
// shortcut for PKCS#7 API
|
||||
var p7v = module.exports = forge.pkcs7asn1 = forge.pkcs7asn1 || {};
|
||||
forge.pkcs7 = forge.pkcs7 || {};
|
||||
forge.pkcs7.asn1 = p7v;
|
||||
|
||||
var contentInfoValidator = {
|
||||
name: 'ContentInfo',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'ContentInfo.ContentType',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OID,
|
||||
constructed: false,
|
||||
capture: 'contentType'
|
||||
}, {
|
||||
name: 'ContentInfo.content',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 0,
|
||||
constructed: true,
|
||||
optional: true,
|
||||
captureAsn1: 'content'
|
||||
}]
|
||||
};
|
||||
p7v.contentInfoValidator = contentInfoValidator;
|
||||
|
||||
var encryptedContentInfoValidator = {
|
||||
name: 'EncryptedContentInfo',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'EncryptedContentInfo.contentType',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OID,
|
||||
constructed: false,
|
||||
capture: 'contentType'
|
||||
}, {
|
||||
name: 'EncryptedContentInfo.contentEncryptionAlgorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'EncryptedContentInfo.contentEncryptionAlgorithm.algorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OID,
|
||||
constructed: false,
|
||||
capture: 'encAlgorithm'
|
||||
}, {
|
||||
name: 'EncryptedContentInfo.contentEncryptionAlgorithm.parameter',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
captureAsn1: 'encParameter'
|
||||
}]
|
||||
}, {
|
||||
name: 'EncryptedContentInfo.encryptedContent',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 0,
|
||||
/* The PKCS#7 structure output by OpenSSL somewhat differs from what
|
||||
* other implementations do generate.
|
||||
*
|
||||
* OpenSSL generates a structure like this:
|
||||
* SEQUENCE {
|
||||
* ...
|
||||
* [0]
|
||||
* 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
|
||||
* C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* Whereas other implementations (and this PKCS#7 module) generate:
|
||||
* SEQUENCE {
|
||||
* ...
|
||||
* [0] {
|
||||
* OCTET STRING
|
||||
* 26 DA 67 D2 17 9C 45 3C B1 2A A8 59 2F 29 33 38
|
||||
* C3 C3 DF 86 71 74 7A 19 9F 40 D0 29 BE 85 90 45
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* In order to support both, we just capture the context specific
|
||||
* field here. The OCTET STRING bit is removed below.
|
||||
*/
|
||||
capture: 'encryptedContent',
|
||||
captureAsn1: 'encryptedContentAsn1'
|
||||
}]
|
||||
};
|
||||
|
||||
p7v.envelopedDataValidator = {
|
||||
name: 'EnvelopedData',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'EnvelopedData.Version',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'version'
|
||||
}, {
|
||||
name: 'EnvelopedData.RecipientInfos',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SET,
|
||||
constructed: true,
|
||||
captureAsn1: 'recipientInfos'
|
||||
}].concat(encryptedContentInfoValidator)
|
||||
};
|
||||
|
||||
p7v.encryptedDataValidator = {
|
||||
name: 'EncryptedData',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'EncryptedData.Version',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'version'
|
||||
}].concat(encryptedContentInfoValidator)
|
||||
};
|
||||
|
||||
var signerValidator = {
|
||||
name: 'SignerInfo',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'SignerInfo.version',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false
|
||||
}, {
|
||||
name: 'SignerInfo.issuerAndSerialNumber',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'SignerInfo.issuerAndSerialNumber.issuer',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
captureAsn1: 'issuer'
|
||||
}, {
|
||||
name: 'SignerInfo.issuerAndSerialNumber.serialNumber',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'serial'
|
||||
}]
|
||||
}, {
|
||||
name: 'SignerInfo.digestAlgorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'SignerInfo.digestAlgorithm.algorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OID,
|
||||
constructed: false,
|
||||
capture: 'digestAlgorithm'
|
||||
}, {
|
||||
name: 'SignerInfo.digestAlgorithm.parameter',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
constructed: false,
|
||||
captureAsn1: 'digestParameter',
|
||||
optional: true
|
||||
}]
|
||||
}, {
|
||||
name: 'SignerInfo.authenticatedAttributes',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 0,
|
||||
constructed: true,
|
||||
optional: true,
|
||||
capture: 'authenticatedAttributes'
|
||||
}, {
|
||||
name: 'SignerInfo.digestEncryptionAlgorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
capture: 'signatureAlgorithm'
|
||||
}, {
|
||||
name: 'SignerInfo.encryptedDigest',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OCTETSTRING,
|
||||
constructed: false,
|
||||
capture: 'signature'
|
||||
}, {
|
||||
name: 'SignerInfo.unauthenticatedAttributes',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 1,
|
||||
constructed: true,
|
||||
optional: true,
|
||||
capture: 'unauthenticatedAttributes'
|
||||
}]
|
||||
};
|
||||
|
||||
p7v.signedDataValidator = {
|
||||
name: 'SignedData',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'SignedData.Version',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'version'
|
||||
}, {
|
||||
name: 'SignedData.DigestAlgorithms',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SET,
|
||||
constructed: true,
|
||||
captureAsn1: 'digestAlgorithms'
|
||||
},
|
||||
contentInfoValidator,
|
||||
{
|
||||
name: 'SignedData.Certificates',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 0,
|
||||
optional: true,
|
||||
captureAsn1: 'certificates'
|
||||
}, {
|
||||
name: 'SignedData.CertificateRevocationLists',
|
||||
tagClass: asn1.Class.CONTEXT_SPECIFIC,
|
||||
type: 1,
|
||||
optional: true,
|
||||
captureAsn1: 'crls'
|
||||
}, {
|
||||
name: 'SignedData.SignerInfos',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SET,
|
||||
capture: 'signerInfos',
|
||||
optional: true,
|
||||
value: [signerValidator]
|
||||
}]
|
||||
};
|
||||
|
||||
p7v.recipientInfoValidator = {
|
||||
name: 'RecipientInfo',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'RecipientInfo.version',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'version'
|
||||
}, {
|
||||
name: 'RecipientInfo.issuerAndSerial',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'RecipientInfo.issuerAndSerial.issuer',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
captureAsn1: 'issuer'
|
||||
}, {
|
||||
name: 'RecipientInfo.issuerAndSerial.serialNumber',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.INTEGER,
|
||||
constructed: false,
|
||||
capture: 'serial'
|
||||
}]
|
||||
}, {
|
||||
name: 'RecipientInfo.keyEncryptionAlgorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.SEQUENCE,
|
||||
constructed: true,
|
||||
value: [{
|
||||
name: 'RecipientInfo.keyEncryptionAlgorithm.algorithm',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OID,
|
||||
constructed: false,
|
||||
capture: 'encAlgorithm'
|
||||
}, {
|
||||
name: 'RecipientInfo.keyEncryptionAlgorithm.parameter',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
constructed: false,
|
||||
captureAsn1: 'encParameter'
|
||||
}]
|
||||
}, {
|
||||
name: 'RecipientInfo.encryptedKey',
|
||||
tagClass: asn1.Class.UNIVERSAL,
|
||||
type: asn1.Type.OCTETSTRING,
|
||||
constructed: false,
|
||||
capture: 'encKey'
|
||||
}]
|
||||
};
|
102
node_modules/node-forge/lib/pki.js
generated
vendored
Normal file
102
node_modules/node-forge/lib/pki.js
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Javascript implementation of a basic Public Key Infrastructure, including
|
||||
* support for RSA public and private keys.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./asn1');
|
||||
require('./oids');
|
||||
require('./pbe');
|
||||
require('./pem');
|
||||
require('./pbkdf2');
|
||||
require('./pkcs12');
|
||||
require('./pss');
|
||||
require('./rsa');
|
||||
require('./util');
|
||||
require('./x509');
|
||||
|
||||
// shortcut for asn.1 API
|
||||
var asn1 = forge.asn1;
|
||||
|
||||
/* Public Key Infrastructure (PKI) implementation. */
|
||||
var pki = module.exports = forge.pki = forge.pki || {};
|
||||
|
||||
/**
|
||||
* NOTE: THIS METHOD IS DEPRECATED. Use pem.decode() instead.
|
||||
*
|
||||
* Converts PEM-formatted data to DER.
|
||||
*
|
||||
* @param pem the PEM-formatted data.
|
||||
*
|
||||
* @return the DER-formatted data.
|
||||
*/
|
||||
pki.pemToDer = function(pem) {
|
||||
var msg = forge.pem.decode(pem)[0];
|
||||
if(msg.procType && msg.procType.type === 'ENCRYPTED') {
|
||||
throw new Error('Could not convert PEM to DER; PEM is encrypted.');
|
||||
}
|
||||
return forge.util.createBuffer(msg.body);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an RSA private key from PEM format.
|
||||
*
|
||||
* @param pem the PEM-formatted private key.
|
||||
*
|
||||
* @return the private key.
|
||||
*/
|
||||
pki.privateKeyFromPem = function(pem) {
|
||||
var msg = forge.pem.decode(pem)[0];
|
||||
|
||||
if(msg.type !== 'PRIVATE KEY' && msg.type !== 'RSA PRIVATE KEY') {
|
||||
var error = new Error('Could not convert private key from PEM; PEM ' +
|
||||
'header type is not "PRIVATE KEY" or "RSA PRIVATE KEY".');
|
||||
error.headerType = msg.type;
|
||||
throw error;
|
||||
}
|
||||
if(msg.procType && msg.procType.type === 'ENCRYPTED') {
|
||||
throw new Error('Could not convert private key from PEM; PEM is encrypted.');
|
||||
}
|
||||
|
||||
// convert DER to ASN.1 object
|
||||
var obj = asn1.fromDer(msg.body);
|
||||
|
||||
return pki.privateKeyFromAsn1(obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an RSA private key to PEM format.
|
||||
*
|
||||
* @param key the private key.
|
||||
* @param maxline the maximum characters per line, defaults to 64.
|
||||
*
|
||||
* @return the PEM-formatted private key.
|
||||
*/
|
||||
pki.privateKeyToPem = function(key, maxline) {
|
||||
// convert to ASN.1, then DER, then PEM-encode
|
||||
var msg = {
|
||||
type: 'RSA PRIVATE KEY',
|
||||
body: asn1.toDer(pki.privateKeyToAsn1(key)).getBytes()
|
||||
};
|
||||
return forge.pem.encode(msg, {maxline: maxline});
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a PrivateKeyInfo to PEM format.
|
||||
*
|
||||
* @param pki the PrivateKeyInfo.
|
||||
* @param maxline the maximum characters per line, defaults to 64.
|
||||
*
|
||||
* @return the PEM-formatted private key.
|
||||
*/
|
||||
pki.privateKeyInfoToPem = function(pki, maxline) {
|
||||
// convert to DER, then PEM-encode
|
||||
var msg = {
|
||||
type: 'PRIVATE KEY',
|
||||
body: asn1.toDer(pki).getBytes()
|
||||
};
|
||||
return forge.pem.encode(msg, {maxline: maxline});
|
||||
};
|
297
node_modules/node-forge/lib/prime.js
generated
vendored
Normal file
297
node_modules/node-forge/lib/prime.js
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
/**
|
||||
* Prime number generation API.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
require('./jsbn');
|
||||
require('./random');
|
||||
|
||||
(function() {
|
||||
|
||||
// forge.prime already defined
|
||||
if(forge.prime) {
|
||||
module.exports = forge.prime;
|
||||
return;
|
||||
}
|
||||
|
||||
/* PRIME API */
|
||||
var prime = module.exports = forge.prime = forge.prime || {};
|
||||
|
||||
var BigInteger = forge.jsbn.BigInteger;
|
||||
|
||||
// primes are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29
|
||||
var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2];
|
||||
var THIRTY = new BigInteger(null);
|
||||
THIRTY.fromInt(30);
|
||||
var op_or = function(x, y) {return x|y;};
|
||||
|
||||
/**
|
||||
* Generates a random probable prime with the given number of bits.
|
||||
*
|
||||
* Alternative algorithms can be specified by name as a string or as an
|
||||
* object with custom options like so:
|
||||
*
|
||||
* {
|
||||
* name: 'PRIMEINC',
|
||||
* options: {
|
||||
* maxBlockTime: <the maximum amount of time to block the main
|
||||
* thread before allowing I/O other JS to run>,
|
||||
* millerRabinTests: <the number of miller-rabin tests to run>,
|
||||
* workerScript: <the worker script URL>,
|
||||
* workers: <the number of web workers (if supported) to use,
|
||||
* -1 to use estimated cores minus one>.
|
||||
* workLoad: the size of the work load, ie: number of possible prime
|
||||
* numbers for each web worker to check per work assignment,
|
||||
* (default: 100).
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param bits the number of bits for the prime number.
|
||||
* @param options the options to use.
|
||||
* [algorithm] the algorithm to use (default: 'PRIMEINC').
|
||||
* [prng] a custom crypto-secure pseudo-random number generator to use,
|
||||
* that must define "getBytesSync".
|
||||
*
|
||||
* @return callback(err, num) called once the operation completes.
|
||||
*/
|
||||
prime.generateProbablePrime = function(bits, options, callback) {
|
||||
if(typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
options = options || {};
|
||||
|
||||
// default to PRIMEINC algorithm
|
||||
var algorithm = options.algorithm || 'PRIMEINC';
|
||||
if(typeof algorithm === 'string') {
|
||||
algorithm = {name: algorithm};
|
||||
}
|
||||
algorithm.options = algorithm.options || {};
|
||||
|
||||
// create prng with api that matches BigInteger secure random
|
||||
var prng = options.prng || forge.random;
|
||||
var rng = {
|
||||
// x is an array to fill with bytes
|
||||
nextBytes: function(x) {
|
||||
var b = prng.getBytesSync(x.length);
|
||||
for(var i = 0; i < x.length; ++i) {
|
||||
x[i] = b.charCodeAt(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(algorithm.name === 'PRIMEINC') {
|
||||
return primeincFindPrime(bits, rng, algorithm.options, callback);
|
||||
}
|
||||
|
||||
throw new Error('Invalid prime generation algorithm: ' + algorithm.name);
|
||||
};
|
||||
|
||||
function primeincFindPrime(bits, rng, options, callback) {
|
||||
if('workers' in options) {
|
||||
return primeincFindPrimeWithWorkers(bits, rng, options, callback);
|
||||
}
|
||||
return primeincFindPrimeWithoutWorkers(bits, rng, options, callback);
|
||||
}
|
||||
|
||||
function primeincFindPrimeWithoutWorkers(bits, rng, options, callback) {
|
||||
// initialize random number
|
||||
var num = generateRandom(bits, rng);
|
||||
|
||||
/* Note: All primes are of the form 30k+i for i < 30 and gcd(30, i)=1. The
|
||||
number we are given is always aligned at 30k + 1. Each time the number is
|
||||
determined not to be prime we add to get to the next 'i', eg: if the number
|
||||
was at 30k + 1 we add 6. */
|
||||
var deltaIdx = 0;
|
||||
|
||||
// get required number of MR tests
|
||||
var mrTests = getMillerRabinTests(num.bitLength());
|
||||
if('millerRabinTests' in options) {
|
||||
mrTests = options.millerRabinTests;
|
||||
}
|
||||
|
||||
// find prime nearest to 'num' for maxBlockTime ms
|
||||
// 10 ms gives 5ms of leeway for other calculations before dropping
|
||||
// below 60fps (1000/60 == 16.67), but in reality, the number will
|
||||
// likely be higher due to an 'atomic' big int modPow
|
||||
var maxBlockTime = 10;
|
||||
if('maxBlockTime' in options) {
|
||||
maxBlockTime = options.maxBlockTime;
|
||||
}
|
||||
|
||||
_primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback);
|
||||
}
|
||||
|
||||
function _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback) {
|
||||
var start = +new Date();
|
||||
do {
|
||||
// overflow, regenerate random number
|
||||
if(num.bitLength() > bits) {
|
||||
num = generateRandom(bits, rng);
|
||||
}
|
||||
// do primality test
|
||||
if(num.isProbablePrime(mrTests)) {
|
||||
return callback(null, num);
|
||||
}
|
||||
// get next potential prime
|
||||
num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0);
|
||||
} while(maxBlockTime < 0 || (+new Date() - start < maxBlockTime));
|
||||
|
||||
// keep trying later
|
||||
forge.util.setImmediate(function() {
|
||||
_primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback);
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: This algorithm is indeterminate in nature because workers
|
||||
// run in parallel looking at different segments of numbers. Even if this
|
||||
// algorithm is run twice with the same input from a predictable RNG, it
|
||||
// may produce different outputs.
|
||||
function primeincFindPrimeWithWorkers(bits, rng, options, callback) {
|
||||
// web workers unavailable
|
||||
if(typeof Worker === 'undefined') {
|
||||
return primeincFindPrimeWithoutWorkers(bits, rng, options, callback);
|
||||
}
|
||||
|
||||
// initialize random number
|
||||
var num = generateRandom(bits, rng);
|
||||
|
||||
// use web workers to generate keys
|
||||
var numWorkers = options.workers;
|
||||
var workLoad = options.workLoad || 100;
|
||||
var range = workLoad * 30 / 8;
|
||||
var workerScript = options.workerScript || 'forge/prime.worker.js';
|
||||
if(numWorkers === -1) {
|
||||
return forge.util.estimateCores(function(err, cores) {
|
||||
if(err) {
|
||||
// default to 2
|
||||
cores = 2;
|
||||
}
|
||||
numWorkers = cores - 1;
|
||||
generate();
|
||||
});
|
||||
}
|
||||
generate();
|
||||
|
||||
function generate() {
|
||||
// require at least 1 worker
|
||||
numWorkers = Math.max(1, numWorkers);
|
||||
|
||||
// TODO: consider optimizing by starting workers outside getPrime() ...
|
||||
// note that in order to clean up they will have to be made internally
|
||||
// asynchronous which may actually be slower
|
||||
|
||||
// start workers immediately
|
||||
var workers = [];
|
||||
for(var i = 0; i < numWorkers; ++i) {
|
||||
// FIXME: fix path or use blob URLs
|
||||
workers[i] = new Worker(workerScript);
|
||||
}
|
||||
var running = numWorkers;
|
||||
|
||||
// listen for requests from workers and assign ranges to find prime
|
||||
for(var i = 0; i < numWorkers; ++i) {
|
||||
workers[i].addEventListener('message', workerMessage);
|
||||
}
|
||||
|
||||
/* Note: The distribution of random numbers is unknown. Therefore, each
|
||||
web worker is continuously allocated a range of numbers to check for a
|
||||
random number until one is found.
|
||||
|
||||
Every 30 numbers will be checked just 8 times, because prime numbers
|
||||
have the form:
|
||||
|
||||
30k+i, for i < 30 and gcd(30, i)=1 (there are 8 values of i for this)
|
||||
|
||||
Therefore, if we want a web worker to run N checks before asking for
|
||||
a new range of numbers, each range must contain N*30/8 numbers.
|
||||
|
||||
For 100 checks (workLoad), this is a range of 375. */
|
||||
|
||||
var found = false;
|
||||
function workerMessage(e) {
|
||||
// ignore message, prime already found
|
||||
if(found) {
|
||||
return;
|
||||
}
|
||||
|
||||
--running;
|
||||
var data = e.data;
|
||||
if(data.found) {
|
||||
// terminate all workers
|
||||
for(var i = 0; i < workers.length; ++i) {
|
||||
workers[i].terminate();
|
||||
}
|
||||
found = true;
|
||||
return callback(null, new BigInteger(data.prime, 16));
|
||||
}
|
||||
|
||||
// overflow, regenerate random number
|
||||
if(num.bitLength() > bits) {
|
||||
num = generateRandom(bits, rng);
|
||||
}
|
||||
|
||||
// assign new range to check
|
||||
var hex = num.toString(16);
|
||||
|
||||
// start prime search
|
||||
e.target.postMessage({
|
||||
hex: hex,
|
||||
workLoad: workLoad
|
||||
});
|
||||
|
||||
num.dAddOffset(range, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random number using the given number of bits and RNG.
|
||||
*
|
||||
* @param bits the number of bits for the number.
|
||||
* @param rng the random number generator to use.
|
||||
*
|
||||
* @return the random number.
|
||||
*/
|
||||
function generateRandom(bits, rng) {
|
||||
var num = new BigInteger(bits, rng);
|
||||
// force MSB set
|
||||
var bits1 = bits - 1;
|
||||
if(!num.testBit(bits1)) {
|
||||
num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num);
|
||||
}
|
||||
// align number on 30k+1 boundary
|
||||
num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0);
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required number of Miller-Rabin tests to generate a
|
||||
* prime with an error probability of (1/2)^80.
|
||||
*
|
||||
* See Handbook of Applied Cryptography Chapter 4, Table 4.4.
|
||||
*
|
||||
* @param bits the bit size.
|
||||
*
|
||||
* @return the required number of iterations.
|
||||
*/
|
||||
function getMillerRabinTests(bits) {
|
||||
if(bits <= 100) return 27;
|
||||
if(bits <= 150) return 18;
|
||||
if(bits <= 200) return 15;
|
||||
if(bits <= 250) return 12;
|
||||
if(bits <= 300) return 9;
|
||||
if(bits <= 350) return 8;
|
||||
if(bits <= 400) return 7;
|
||||
if(bits <= 500) return 6;
|
||||
if(bits <= 600) return 5;
|
||||
if(bits <= 800) return 4;
|
||||
if(bits <= 1250) return 3;
|
||||
return 2;
|
||||
}
|
||||
|
||||
})();
|
168
node_modules/node-forge/lib/prime.worker.js
generated
vendored
Normal file
168
node_modules/node-forge/lib/prime.worker.js
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
/**
|
||||
* RSA Key Generation Worker.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
// worker is built using CommonJS syntax to include all code in one worker file
|
||||
//importScripts('jsbn.js');
|
||||
var forge = require('./forge');
|
||||
require('./jsbn');
|
||||
|
||||
// prime constants
|
||||
var LOW_PRIMES = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
|
||||
var LP_LIMIT = (1 << 26) / LOW_PRIMES[LOW_PRIMES.length - 1];
|
||||
|
||||
var BigInteger = forge.jsbn.BigInteger;
|
||||
var BIG_TWO = new BigInteger(null);
|
||||
BIG_TWO.fromInt(2);
|
||||
|
||||
self.addEventListener('message', function(e) {
|
||||
var result = findPrime(e.data);
|
||||
self.postMessage(result);
|
||||
});
|
||||
|
||||
// start receiving ranges to check
|
||||
self.postMessage({found: false});
|
||||
|
||||
// primes are 30k+i for i = 1, 7, 11, 13, 17, 19, 23, 29
|
||||
var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2];
|
||||
|
||||
function findPrime(data) {
|
||||
// TODO: abstract based on data.algorithm (PRIMEINC vs. others)
|
||||
|
||||
// create BigInteger from given random bytes
|
||||
var num = new BigInteger(data.hex, 16);
|
||||
|
||||
/* Note: All primes are of the form 30k+i for i < 30 and gcd(30, i)=1. The
|
||||
number we are given is always aligned at 30k + 1. Each time the number is
|
||||
determined not to be prime we add to get to the next 'i', eg: if the number
|
||||
was at 30k + 1 we add 6. */
|
||||
var deltaIdx = 0;
|
||||
|
||||
// find nearest prime
|
||||
var workLoad = data.workLoad;
|
||||
for(var i = 0; i < workLoad; ++i) {
|
||||
// do primality test
|
||||
if(isProbablePrime(num)) {
|
||||
return {found: true, prime: num.toString(16)};
|
||||
}
|
||||
// get next potential prime
|
||||
num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0);
|
||||
}
|
||||
|
||||
return {found: false};
|
||||
}
|
||||
|
||||
function isProbablePrime(n) {
|
||||
// divide by low primes, ignore even checks, etc (n alread aligned properly)
|
||||
var i = 1;
|
||||
while(i < LOW_PRIMES.length) {
|
||||
var m = LOW_PRIMES[i];
|
||||
var j = i + 1;
|
||||
while(j < LOW_PRIMES.length && m < LP_LIMIT) {
|
||||
m *= LOW_PRIMES[j++];
|
||||
}
|
||||
m = n.modInt(m);
|
||||
while(i < j) {
|
||||
if(m % LOW_PRIMES[i++] === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return runMillerRabin(n);
|
||||
}
|
||||
|
||||
// HAC 4.24, Miller-Rabin
|
||||
function runMillerRabin(n) {
|
||||
// n1 = n - 1
|
||||
var n1 = n.subtract(BigInteger.ONE);
|
||||
|
||||
// get s and d such that n1 = 2^s * d
|
||||
var s = n1.getLowestSetBit();
|
||||
if(s <= 0) {
|
||||
return false;
|
||||
}
|
||||
var d = n1.shiftRight(s);
|
||||
|
||||
var k = _getMillerRabinTests(n.bitLength());
|
||||
var prng = getPrng();
|
||||
var a;
|
||||
for(var i = 0; i < k; ++i) {
|
||||
// select witness 'a' at random from between 1 and n - 1
|
||||
do {
|
||||
a = new BigInteger(n.bitLength(), prng);
|
||||
} while(a.compareTo(BigInteger.ONE) <= 0 || a.compareTo(n1) >= 0);
|
||||
|
||||
/* See if 'a' is a composite witness. */
|
||||
|
||||
// x = a^d mod n
|
||||
var x = a.modPow(d, n);
|
||||
|
||||
// probably prime
|
||||
if(x.compareTo(BigInteger.ONE) === 0 || x.compareTo(n1) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var j = s;
|
||||
while(--j) {
|
||||
// x = x^2 mod a
|
||||
x = x.modPowInt(2, n);
|
||||
|
||||
// 'n' is composite because no previous x == -1 mod n
|
||||
if(x.compareTo(BigInteger.ONE) === 0) {
|
||||
return false;
|
||||
}
|
||||
// x == -1 mod n, so probably prime
|
||||
if(x.compareTo(n1) === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 'x' is first_x^(n1/2) and is not +/- 1, so 'n' is not prime
|
||||
if(j === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get pseudo random number generator
|
||||
function getPrng() {
|
||||
// create prng with api that matches BigInteger secure random
|
||||
return {
|
||||
// x is an array to fill with bytes
|
||||
nextBytes: function(x) {
|
||||
for(var i = 0; i < x.length; ++i) {
|
||||
x[i] = Math.floor(Math.random() * 0xFF);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required number of Miller-Rabin tests to generate a
|
||||
* prime with an error probability of (1/2)^80.
|
||||
*
|
||||
* See Handbook of Applied Cryptography Chapter 4, Table 4.4.
|
||||
*
|
||||
* @param bits the bit size.
|
||||
*
|
||||
* @return the required number of iterations.
|
||||
*/
|
||||
function _getMillerRabinTests(bits) {
|
||||
if(bits <= 100) return 27;
|
||||
if(bits <= 150) return 18;
|
||||
if(bits <= 200) return 15;
|
||||
if(bits <= 250) return 12;
|
||||
if(bits <= 300) return 9;
|
||||
if(bits <= 350) return 8;
|
||||
if(bits <= 400) return 7;
|
||||
if(bits <= 500) return 6;
|
||||
if(bits <= 600) return 5;
|
||||
if(bits <= 800) return 4;
|
||||
if(bits <= 1250) return 3;
|
||||
return 2;
|
||||
}
|
420
node_modules/node-forge/lib/prng.js
generated
vendored
Normal file
420
node_modules/node-forge/lib/prng.js
generated
vendored
Normal file
@ -0,0 +1,420 @@
|
||||
/**
|
||||
* A javascript implementation of a cryptographically-secure
|
||||
* Pseudo Random Number Generator (PRNG). The Fortuna algorithm is followed
|
||||
* here though the use of SHA-256 is not enforced; when generating an
|
||||
* a PRNG context, the hashing algorithm and block cipher used for
|
||||
* the generator are specified via a plugin.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
var _crypto = null;
|
||||
if(forge.util.isNodejs && !forge.options.usePureJavaScript &&
|
||||
!process.versions['node-webkit']) {
|
||||
_crypto = require('crypto');
|
||||
}
|
||||
|
||||
/* PRNG API */
|
||||
var prng = module.exports = forge.prng = forge.prng || {};
|
||||
|
||||
/**
|
||||
* Creates a new PRNG context.
|
||||
*
|
||||
* A PRNG plugin must be passed in that will provide:
|
||||
*
|
||||
* 1. A function that initializes the key and seed of a PRNG context. It
|
||||
* will be given a 16 byte key and a 16 byte seed. Any key expansion
|
||||
* or transformation of the seed from a byte string into an array of
|
||||
* integers (or similar) should be performed.
|
||||
* 2. The cryptographic function used by the generator. It takes a key and
|
||||
* a seed.
|
||||
* 3. A seed increment function. It takes the seed and returns seed + 1.
|
||||
* 4. An api to create a message digest.
|
||||
*
|
||||
* For an example, see random.js.
|
||||
*
|
||||
* @param plugin the PRNG plugin to use.
|
||||
*/
|
||||
prng.create = function(plugin) {
|
||||
var ctx = {
|
||||
plugin: plugin,
|
||||
key: null,
|
||||
seed: null,
|
||||
time: null,
|
||||
// number of reseeds so far
|
||||
reseeds: 0,
|
||||
// amount of data generated so far
|
||||
generated: 0,
|
||||
// no initial key bytes
|
||||
keyBytes: ''
|
||||
};
|
||||
|
||||
// create 32 entropy pools (each is a message digest)
|
||||
var md = plugin.md;
|
||||
var pools = new Array(32);
|
||||
for(var i = 0; i < 32; ++i) {
|
||||
pools[i] = md.create();
|
||||
}
|
||||
ctx.pools = pools;
|
||||
|
||||
// entropy pools are written to cyclically, starting at index 0
|
||||
ctx.pool = 0;
|
||||
|
||||
/**
|
||||
* Generates random bytes. The bytes may be generated synchronously or
|
||||
* asynchronously. Web workers must use the asynchronous interface or
|
||||
* else the behavior is undefined.
|
||||
*
|
||||
* @param count the number of random bytes to generate.
|
||||
* @param [callback(err, bytes)] called once the operation completes.
|
||||
*
|
||||
* @return count random bytes as a string.
|
||||
*/
|
||||
ctx.generate = function(count, callback) {
|
||||
// do synchronously
|
||||
if(!callback) {
|
||||
return ctx.generateSync(count);
|
||||
}
|
||||
|
||||
// simple generator using counter-based CBC
|
||||
var cipher = ctx.plugin.cipher;
|
||||
var increment = ctx.plugin.increment;
|
||||
var formatKey = ctx.plugin.formatKey;
|
||||
var formatSeed = ctx.plugin.formatSeed;
|
||||
var b = forge.util.createBuffer();
|
||||
|
||||
// paranoid deviation from Fortuna:
|
||||
// reset key for every request to protect previously
|
||||
// generated random bytes should the key be discovered;
|
||||
// there is no 100ms based reseeding because of this
|
||||
// forced reseed for every `generate` call
|
||||
ctx.key = null;
|
||||
|
||||
generate();
|
||||
|
||||
function generate(err) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
// sufficient bytes generated
|
||||
if(b.length() >= count) {
|
||||
return callback(null, b.getBytes(count));
|
||||
}
|
||||
|
||||
// if amount of data generated is greater than 1 MiB, trigger reseed
|
||||
if(ctx.generated > 0xfffff) {
|
||||
ctx.key = null;
|
||||
}
|
||||
|
||||
if(ctx.key === null) {
|
||||
// prevent stack overflow
|
||||
return forge.util.nextTick(function() {
|
||||
_reseed(generate);
|
||||
});
|
||||
}
|
||||
|
||||
// generate the random bytes
|
||||
var bytes = cipher(ctx.key, ctx.seed);
|
||||
ctx.generated += bytes.length;
|
||||
b.putBytes(bytes);
|
||||
|
||||
// generate bytes for a new key and seed
|
||||
ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed)));
|
||||
ctx.seed = formatSeed(cipher(ctx.key, ctx.seed));
|
||||
|
||||
forge.util.setImmediate(generate);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates random bytes synchronously.
|
||||
*
|
||||
* @param count the number of random bytes to generate.
|
||||
*
|
||||
* @return count random bytes as a string.
|
||||
*/
|
||||
ctx.generateSync = function(count) {
|
||||
// simple generator using counter-based CBC
|
||||
var cipher = ctx.plugin.cipher;
|
||||
var increment = ctx.plugin.increment;
|
||||
var formatKey = ctx.plugin.formatKey;
|
||||
var formatSeed = ctx.plugin.formatSeed;
|
||||
|
||||
// paranoid deviation from Fortuna:
|
||||
// reset key for every request to protect previously
|
||||
// generated random bytes should the key be discovered;
|
||||
// there is no 100ms based reseeding because of this
|
||||
// forced reseed for every `generateSync` call
|
||||
ctx.key = null;
|
||||
|
||||
var b = forge.util.createBuffer();
|
||||
while(b.length() < count) {
|
||||
// if amount of data generated is greater than 1 MiB, trigger reseed
|
||||
if(ctx.generated > 0xfffff) {
|
||||
ctx.key = null;
|
||||
}
|
||||
|
||||
if(ctx.key === null) {
|
||||
_reseedSync();
|
||||
}
|
||||
|
||||
// generate the random bytes
|
||||
var bytes = cipher(ctx.key, ctx.seed);
|
||||
ctx.generated += bytes.length;
|
||||
b.putBytes(bytes);
|
||||
|
||||
// generate bytes for a new key and seed
|
||||
ctx.key = formatKey(cipher(ctx.key, increment(ctx.seed)));
|
||||
ctx.seed = formatSeed(cipher(ctx.key, ctx.seed));
|
||||
}
|
||||
|
||||
return b.getBytes(count);
|
||||
};
|
||||
|
||||
/**
|
||||
* Private function that asynchronously reseeds a generator.
|
||||
*
|
||||
* @param callback(err) called once the operation completes.
|
||||
*/
|
||||
function _reseed(callback) {
|
||||
if(ctx.pools[0].messageLength >= 32) {
|
||||
_seed();
|
||||
return callback();
|
||||
}
|
||||
// not enough seed data...
|
||||
var needed = (32 - ctx.pools[0].messageLength) << 5;
|
||||
ctx.seedFile(needed, function(err, bytes) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
ctx.collect(bytes);
|
||||
_seed();
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function that synchronously reseeds a generator.
|
||||
*/
|
||||
function _reseedSync() {
|
||||
if(ctx.pools[0].messageLength >= 32) {
|
||||
return _seed();
|
||||
}
|
||||
// not enough seed data...
|
||||
var needed = (32 - ctx.pools[0].messageLength) << 5;
|
||||
ctx.collect(ctx.seedFileSync(needed));
|
||||
_seed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private function that seeds a generator once enough bytes are available.
|
||||
*/
|
||||
function _seed() {
|
||||
// update reseed count
|
||||
ctx.reseeds = (ctx.reseeds === 0xffffffff) ? 0 : ctx.reseeds + 1;
|
||||
|
||||
// goal is to update `key` via:
|
||||
// key = hash(key + s)
|
||||
// where 's' is all collected entropy from selected pools, then...
|
||||
|
||||
// create a plugin-based message digest
|
||||
var md = ctx.plugin.md.create();
|
||||
|
||||
// consume current key bytes
|
||||
md.update(ctx.keyBytes);
|
||||
|
||||
// digest the entropy of pools whose index k meet the
|
||||
// condition 'n mod 2^k == 0' where n is the number of reseeds
|
||||
var _2powK = 1;
|
||||
for(var k = 0; k < 32; ++k) {
|
||||
if(ctx.reseeds % _2powK === 0) {
|
||||
md.update(ctx.pools[k].digest().getBytes());
|
||||
ctx.pools[k].start();
|
||||
}
|
||||
_2powK = _2powK << 1;
|
||||
}
|
||||
|
||||
// get digest for key bytes
|
||||
ctx.keyBytes = md.digest().getBytes();
|
||||
|
||||
// paranoid deviation from Fortuna:
|
||||
// update `seed` via `seed = hash(key)`
|
||||
// instead of initializing to zero once and only
|
||||
// ever incrementing it
|
||||
md.start();
|
||||
md.update(ctx.keyBytes);
|
||||
var seedBytes = md.digest().getBytes();
|
||||
|
||||
// update state
|
||||
ctx.key = ctx.plugin.formatKey(ctx.keyBytes);
|
||||
ctx.seed = ctx.plugin.formatSeed(seedBytes);
|
||||
ctx.generated = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The built-in default seedFile. This seedFile is used when entropy
|
||||
* is needed immediately.
|
||||
*
|
||||
* @param needed the number of bytes that are needed.
|
||||
*
|
||||
* @return the random bytes.
|
||||
*/
|
||||
function defaultSeedFile(needed) {
|
||||
// use window.crypto.getRandomValues strong source of entropy if available
|
||||
var getRandomValues = null;
|
||||
if(typeof window !== 'undefined') {
|
||||
var _crypto = window.crypto || window.msCrypto;
|
||||
if(_crypto && _crypto.getRandomValues) {
|
||||
getRandomValues = function(arr) {
|
||||
return _crypto.getRandomValues(arr);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var b = forge.util.createBuffer();
|
||||
if(getRandomValues) {
|
||||
while(b.length() < needed) {
|
||||
// max byte length is 65536 before QuotaExceededError is thrown
|
||||
// http://www.w3.org/TR/WebCryptoAPI/#RandomSource-method-getRandomValues
|
||||
var count = Math.max(1, Math.min(needed - b.length(), 65536) / 4);
|
||||
var entropy = new Uint32Array(Math.floor(count));
|
||||
try {
|
||||
getRandomValues(entropy);
|
||||
for(var i = 0; i < entropy.length; ++i) {
|
||||
b.putInt32(entropy[i]);
|
||||
}
|
||||
} catch(e) {
|
||||
/* only ignore QuotaExceededError */
|
||||
if(!(typeof QuotaExceededError !== 'undefined' &&
|
||||
e instanceof QuotaExceededError)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// be sad and add some weak random data
|
||||
if(b.length() < needed) {
|
||||
/* Draws from Park-Miller "minimal standard" 31 bit PRNG,
|
||||
implemented with David G. Carta's optimization: with 32 bit math
|
||||
and without division (Public Domain). */
|
||||
var hi, lo, next;
|
||||
var seed = Math.floor(Math.random() * 0x010000);
|
||||
while(b.length() < needed) {
|
||||
lo = 16807 * (seed & 0xFFFF);
|
||||
hi = 16807 * (seed >> 16);
|
||||
lo += (hi & 0x7FFF) << 16;
|
||||
lo += hi >> 15;
|
||||
lo = (lo & 0x7FFFFFFF) + (lo >> 31);
|
||||
seed = lo & 0xFFFFFFFF;
|
||||
|
||||
// consume lower 3 bytes of seed
|
||||
for(var i = 0; i < 3; ++i) {
|
||||
// throw in more pseudo random
|
||||
next = seed >>> (i << 3);
|
||||
next ^= Math.floor(Math.random() * 0x0100);
|
||||
b.putByte(String.fromCharCode(next & 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.getBytes(needed);
|
||||
}
|
||||
// initialize seed file APIs
|
||||
if(_crypto) {
|
||||
// use nodejs async API
|
||||
ctx.seedFile = function(needed, callback) {
|
||||
_crypto.randomBytes(needed, function(err, bytes) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, bytes.toString());
|
||||
});
|
||||
};
|
||||
// use nodejs sync API
|
||||
ctx.seedFileSync = function(needed) {
|
||||
return _crypto.randomBytes(needed).toString();
|
||||
};
|
||||
} else {
|
||||
ctx.seedFile = function(needed, callback) {
|
||||
try {
|
||||
callback(null, defaultSeedFile(needed));
|
||||
} catch(e) {
|
||||
callback(e);
|
||||
}
|
||||
};
|
||||
ctx.seedFileSync = defaultSeedFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds entropy to a prng ctx's accumulator.
|
||||
*
|
||||
* @param bytes the bytes of entropy as a string.
|
||||
*/
|
||||
ctx.collect = function(bytes) {
|
||||
// iterate over pools distributing entropy cyclically
|
||||
var count = bytes.length;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
ctx.pools[ctx.pool].update(bytes.substr(i, 1));
|
||||
ctx.pool = (ctx.pool === 31) ? 0 : ctx.pool + 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Collects an integer of n bits.
|
||||
*
|
||||
* @param i the integer entropy.
|
||||
* @param n the number of bits in the integer.
|
||||
*/
|
||||
ctx.collectInt = function(i, n) {
|
||||
var bytes = '';
|
||||
for(var x = 0; x < n; x += 8) {
|
||||
bytes += String.fromCharCode((i >> x) & 0xFF);
|
||||
}
|
||||
ctx.collect(bytes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a Web Worker to receive immediate entropy from the main thread.
|
||||
* This method is required until Web Workers can access the native crypto
|
||||
* API. This method should be called twice for each created worker, once in
|
||||
* the main thread, and once in the worker itself.
|
||||
*
|
||||
* @param worker the worker to register.
|
||||
*/
|
||||
ctx.registerWorker = function(worker) {
|
||||
// worker receives random bytes
|
||||
if(worker === self) {
|
||||
ctx.seedFile = function(needed, callback) {
|
||||
function listener(e) {
|
||||
var data = e.data;
|
||||
if(data.forge && data.forge.prng) {
|
||||
self.removeEventListener('message', listener);
|
||||
callback(data.forge.prng.err, data.forge.prng.bytes);
|
||||
}
|
||||
}
|
||||
self.addEventListener('message', listener);
|
||||
self.postMessage({forge: {prng: {needed: needed}}});
|
||||
};
|
||||
} else {
|
||||
// main thread sends random bytes upon request
|
||||
var listener = function(e) {
|
||||
var data = e.data;
|
||||
if(data.forge && data.forge.prng) {
|
||||
ctx.seedFile(data.forge.prng.needed, function(err, bytes) {
|
||||
worker.postMessage({forge: {prng: {err: err, bytes: bytes}}});
|
||||
});
|
||||
}
|
||||
};
|
||||
// TODO: do we need to remove the event listener when the worker dies?
|
||||
worker.addEventListener('message', listener);
|
||||
}
|
||||
};
|
||||
|
||||
return ctx;
|
||||
};
|
241
node_modules/node-forge/lib/pss.js
generated
vendored
Normal file
241
node_modules/node-forge/lib/pss.js
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
/**
|
||||
* Javascript implementation of PKCS#1 PSS signature padding.
|
||||
*
|
||||
* @author Stefan Siegl
|
||||
*
|
||||
* Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./random');
|
||||
require('./util');
|
||||
|
||||
// shortcut for PSS API
|
||||
var pss = module.exports = forge.pss = forge.pss || {};
|
||||
|
||||
/**
|
||||
* Creates a PSS signature scheme object.
|
||||
*
|
||||
* There are several ways to provide a salt for encoding:
|
||||
*
|
||||
* 1. Specify the saltLength only and the built-in PRNG will generate it.
|
||||
* 2. Specify the saltLength and a custom PRNG with 'getBytesSync' defined that
|
||||
* will be used.
|
||||
* 3. Specify the salt itself as a forge.util.ByteBuffer.
|
||||
*
|
||||
* @param options the options to use:
|
||||
* md the message digest object to use, a forge md instance.
|
||||
* mgf the mask generation function to use, a forge mgf instance.
|
||||
* [saltLength] the length of the salt in octets.
|
||||
* [prng] the pseudo-random number generator to use to produce a salt.
|
||||
* [salt] the salt to use when encoding.
|
||||
*
|
||||
* @return a signature scheme object.
|
||||
*/
|
||||
pss.create = function(options) {
|
||||
// backwards compatibility w/legacy args: hash, mgf, sLen
|
||||
if(arguments.length === 3) {
|
||||
options = {
|
||||
md: arguments[0],
|
||||
mgf: arguments[1],
|
||||
saltLength: arguments[2]
|
||||
};
|
||||
}
|
||||
|
||||
var hash = options.md;
|
||||
var mgf = options.mgf;
|
||||
var hLen = hash.digestLength;
|
||||
|
||||
var salt_ = options.salt || null;
|
||||
if(typeof salt_ === 'string') {
|
||||
// assume binary-encoded string
|
||||
salt_ = forge.util.createBuffer(salt_);
|
||||
}
|
||||
|
||||
var sLen;
|
||||
if('saltLength' in options) {
|
||||
sLen = options.saltLength;
|
||||
} else if(salt_ !== null) {
|
||||
sLen = salt_.length();
|
||||
} else {
|
||||
throw new Error('Salt length not specified or specific salt not given.');
|
||||
}
|
||||
|
||||
if(salt_ !== null && salt_.length() !== sLen) {
|
||||
throw new Error('Given salt length does not match length of given salt.');
|
||||
}
|
||||
|
||||
var prng = options.prng || forge.random;
|
||||
|
||||
var pssobj = {};
|
||||
|
||||
/**
|
||||
* Encodes a PSS signature.
|
||||
*
|
||||
* This function implements EMSA-PSS-ENCODE as per RFC 3447, section 9.1.1.
|
||||
*
|
||||
* @param md the message digest object with the hash to sign.
|
||||
* @param modsBits the length of the RSA modulus in bits.
|
||||
*
|
||||
* @return the encoded message as a binary-encoded string of length
|
||||
* ceil((modBits - 1) / 8).
|
||||
*/
|
||||
pssobj.encode = function(md, modBits) {
|
||||
var i;
|
||||
var emBits = modBits - 1;
|
||||
var emLen = Math.ceil(emBits / 8);
|
||||
|
||||
/* 2. Let mHash = Hash(M), an octet string of length hLen. */
|
||||
var mHash = md.digest().getBytes();
|
||||
|
||||
/* 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. */
|
||||
if(emLen < hLen + sLen + 2) {
|
||||
throw new Error('Message is too long to encrypt.');
|
||||
}
|
||||
|
||||
/* 4. Generate a random octet string salt of length sLen; if sLen = 0,
|
||||
* then salt is the empty string. */
|
||||
var salt;
|
||||
if(salt_ === null) {
|
||||
salt = prng.getBytesSync(sLen);
|
||||
} else {
|
||||
salt = salt_.bytes();
|
||||
}
|
||||
|
||||
/* 5. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; */
|
||||
var m_ = new forge.util.ByteBuffer();
|
||||
m_.fillWithByte(0, 8);
|
||||
m_.putBytes(mHash);
|
||||
m_.putBytes(salt);
|
||||
|
||||
/* 6. Let H = Hash(M'), an octet string of length hLen. */
|
||||
hash.start();
|
||||
hash.update(m_.getBytes());
|
||||
var h = hash.digest().getBytes();
|
||||
|
||||
/* 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
|
||||
* zero octets. The length of PS may be 0. */
|
||||
var ps = new forge.util.ByteBuffer();
|
||||
ps.fillWithByte(0, emLen - sLen - hLen - 2);
|
||||
|
||||
/* 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
|
||||
* emLen - hLen - 1. */
|
||||
ps.putByte(0x01);
|
||||
ps.putBytes(salt);
|
||||
var db = ps.getBytes();
|
||||
|
||||
/* 9. Let dbMask = MGF(H, emLen - hLen - 1). */
|
||||
var maskLen = emLen - hLen - 1;
|
||||
var dbMask = mgf.generate(h, maskLen);
|
||||
|
||||
/* 10. Let maskedDB = DB \xor dbMask. */
|
||||
var maskedDB = '';
|
||||
for(i = 0; i < maskLen; i++) {
|
||||
maskedDB += String.fromCharCode(db.charCodeAt(i) ^ dbMask.charCodeAt(i));
|
||||
}
|
||||
|
||||
/* 11. Set the leftmost 8emLen - emBits bits of the leftmost octet in
|
||||
* maskedDB to zero. */
|
||||
var mask = (0xFF00 >> (8 * emLen - emBits)) & 0xFF;
|
||||
maskedDB = String.fromCharCode(maskedDB.charCodeAt(0) & ~mask) +
|
||||
maskedDB.substr(1);
|
||||
|
||||
/* 12. Let EM = maskedDB || H || 0xbc.
|
||||
* 13. Output EM. */
|
||||
return maskedDB + h + String.fromCharCode(0xbc);
|
||||
};
|
||||
|
||||
/**
|
||||
* Verifies a PSS signature.
|
||||
*
|
||||
* This function implements EMSA-PSS-VERIFY as per RFC 3447, section 9.1.2.
|
||||
*
|
||||
* @param mHash the message digest hash, as a binary-encoded string, to
|
||||
* compare against the signature.
|
||||
* @param em the encoded message, as a binary-encoded string
|
||||
* (RSA decryption result).
|
||||
* @param modsBits the length of the RSA modulus in bits.
|
||||
*
|
||||
* @return true if the signature was verified, false if not.
|
||||
*/
|
||||
pssobj.verify = function(mHash, em, modBits) {
|
||||
var i;
|
||||
var emBits = modBits - 1;
|
||||
var emLen = Math.ceil(emBits / 8);
|
||||
|
||||
/* c. Convert the message representative m to an encoded message EM
|
||||
* of length emLen = ceil((modBits - 1) / 8) octets, where modBits
|
||||
* is the length in bits of the RSA modulus n */
|
||||
em = em.substr(-emLen);
|
||||
|
||||
/* 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. */
|
||||
if(emLen < hLen + sLen + 2) {
|
||||
throw new Error('Inconsistent parameters to PSS signature verification.');
|
||||
}
|
||||
|
||||
/* 4. If the rightmost octet of EM does not have hexadecimal value
|
||||
* 0xbc, output "inconsistent" and stop. */
|
||||
if(em.charCodeAt(emLen - 1) !== 0xbc) {
|
||||
throw new Error('Encoded message does not end in 0xBC.');
|
||||
}
|
||||
|
||||
/* 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
|
||||
* let H be the next hLen octets. */
|
||||
var maskLen = emLen - hLen - 1;
|
||||
var maskedDB = em.substr(0, maskLen);
|
||||
var h = em.substr(maskLen, hLen);
|
||||
|
||||
/* 6. If the leftmost 8emLen - emBits bits of the leftmost octet in
|
||||
* maskedDB are not all equal to zero, output "inconsistent" and stop. */
|
||||
var mask = (0xFF00 >> (8 * emLen - emBits)) & 0xFF;
|
||||
if((maskedDB.charCodeAt(0) & mask) !== 0) {
|
||||
throw new Error('Bits beyond keysize not zero as expected.');
|
||||
}
|
||||
|
||||
/* 7. Let dbMask = MGF(H, emLen - hLen - 1). */
|
||||
var dbMask = mgf.generate(h, maskLen);
|
||||
|
||||
/* 8. Let DB = maskedDB \xor dbMask. */
|
||||
var db = '';
|
||||
for(i = 0; i < maskLen; i++) {
|
||||
db += String.fromCharCode(maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i));
|
||||
}
|
||||
|
||||
/* 9. Set the leftmost 8emLen - emBits bits of the leftmost octet
|
||||
* in DB to zero. */
|
||||
db = String.fromCharCode(db.charCodeAt(0) & ~mask) + db.substr(1);
|
||||
|
||||
/* 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
|
||||
* or if the octet at position emLen - hLen - sLen - 1 (the leftmost
|
||||
* position is "position 1") does not have hexadecimal value 0x01,
|
||||
* output "inconsistent" and stop. */
|
||||
var checkLen = emLen - hLen - sLen - 2;
|
||||
for(i = 0; i < checkLen; i++) {
|
||||
if(db.charCodeAt(i) !== 0x00) {
|
||||
throw new Error('Leftmost octets not zero as expected');
|
||||
}
|
||||
}
|
||||
|
||||
if(db.charCodeAt(checkLen) !== 0x01) {
|
||||
throw new Error('Inconsistent PSS signature, 0x01 marker not found');
|
||||
}
|
||||
|
||||
/* 11. Let salt be the last sLen octets of DB. */
|
||||
var salt = db.substr(-sLen);
|
||||
|
||||
/* 12. Let M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */
|
||||
var m_ = new forge.util.ByteBuffer();
|
||||
m_.fillWithByte(0, 8);
|
||||
m_.putBytes(mHash);
|
||||
m_.putBytes(salt);
|
||||
|
||||
/* 13. Let H' = Hash(M'), an octet string of length hLen. */
|
||||
hash.start();
|
||||
hash.update(m_.getBytes());
|
||||
var h_ = hash.digest().getBytes();
|
||||
|
||||
/* 14. If H = H', output "consistent." Otherwise, output "inconsistent." */
|
||||
return h === h_;
|
||||
};
|
||||
|
||||
return pssobj;
|
||||
};
|
191
node_modules/node-forge/lib/random.js
generated
vendored
Normal file
191
node_modules/node-forge/lib/random.js
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
/**
|
||||
* An API for getting cryptographically-secure random bytes. The bytes are
|
||||
* generated using the Fortuna algorithm devised by Bruce Schneier and
|
||||
* Niels Ferguson.
|
||||
*
|
||||
* Getting strong random bytes is not yet easy to do in javascript. The only
|
||||
* truish random entropy that can be collected is from the mouse, keyboard, or
|
||||
* from timing with respect to page loads, etc. This generator makes a poor
|
||||
* attempt at providing random bytes when those sources haven't yet provided
|
||||
* enough entropy to initially seed or to reseed the PRNG.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2009-2014 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./aes');
|
||||
require('./sha256');
|
||||
require('./prng');
|
||||
require('./util');
|
||||
|
||||
(function() {
|
||||
|
||||
// forge.random already defined
|
||||
if(forge.random && forge.random.getBytes) {
|
||||
module.exports = forge.random;
|
||||
return;
|
||||
}
|
||||
|
||||
(function(jQuery) {
|
||||
|
||||
// the default prng plugin, uses AES-128
|
||||
var prng_aes = {};
|
||||
var _prng_aes_output = new Array(4);
|
||||
var _prng_aes_buffer = forge.util.createBuffer();
|
||||
prng_aes.formatKey = function(key) {
|
||||
// convert the key into 32-bit integers
|
||||
var tmp = forge.util.createBuffer(key);
|
||||
key = new Array(4);
|
||||
key[0] = tmp.getInt32();
|
||||
key[1] = tmp.getInt32();
|
||||
key[2] = tmp.getInt32();
|
||||
key[3] = tmp.getInt32();
|
||||
|
||||
// return the expanded key
|
||||
return forge.aes._expandKey(key, false);
|
||||
};
|
||||
prng_aes.formatSeed = function(seed) {
|
||||
// convert seed into 32-bit integers
|
||||
var tmp = forge.util.createBuffer(seed);
|
||||
seed = new Array(4);
|
||||
seed[0] = tmp.getInt32();
|
||||
seed[1] = tmp.getInt32();
|
||||
seed[2] = tmp.getInt32();
|
||||
seed[3] = tmp.getInt32();
|
||||
return seed;
|
||||
};
|
||||
prng_aes.cipher = function(key, seed) {
|
||||
forge.aes._updateBlock(key, seed, _prng_aes_output, false);
|
||||
_prng_aes_buffer.putInt32(_prng_aes_output[0]);
|
||||
_prng_aes_buffer.putInt32(_prng_aes_output[1]);
|
||||
_prng_aes_buffer.putInt32(_prng_aes_output[2]);
|
||||
_prng_aes_buffer.putInt32(_prng_aes_output[3]);
|
||||
return _prng_aes_buffer.getBytes();
|
||||
};
|
||||
prng_aes.increment = function(seed) {
|
||||
// FIXME: do we care about carry or signed issues?
|
||||
++seed[3];
|
||||
return seed;
|
||||
};
|
||||
prng_aes.md = forge.md.sha256;
|
||||
|
||||
/**
|
||||
* Creates a new PRNG.
|
||||
*/
|
||||
function spawnPrng() {
|
||||
var ctx = forge.prng.create(prng_aes);
|
||||
|
||||
/**
|
||||
* Gets random bytes. If a native secure crypto API is unavailable, this
|
||||
* method tries to make the bytes more unpredictable by drawing from data that
|
||||
* can be collected from the user of the browser, eg: mouse movement.
|
||||
*
|
||||
* If a callback is given, this method will be called asynchronously.
|
||||
*
|
||||
* @param count the number of random bytes to get.
|
||||
* @param [callback(err, bytes)] called once the operation completes.
|
||||
*
|
||||
* @return the random bytes in a string.
|
||||
*/
|
||||
ctx.getBytes = function(count, callback) {
|
||||
return ctx.generate(count, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets random bytes asynchronously. If a native secure crypto API is
|
||||
* unavailable, this method tries to make the bytes more unpredictable by
|
||||
* drawing from data that can be collected from the user of the browser,
|
||||
* eg: mouse movement.
|
||||
*
|
||||
* @param count the number of random bytes to get.
|
||||
*
|
||||
* @return the random bytes in a string.
|
||||
*/
|
||||
ctx.getBytesSync = function(count) {
|
||||
return ctx.generate(count);
|
||||
};
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
// create default prng context
|
||||
var _ctx = spawnPrng();
|
||||
|
||||
// add other sources of entropy only if window.crypto.getRandomValues is not
|
||||
// available -- otherwise this source will be automatically used by the prng
|
||||
var getRandomValues = null;
|
||||
if(typeof window !== 'undefined') {
|
||||
var _crypto = window.crypto || window.msCrypto;
|
||||
if(_crypto && _crypto.getRandomValues) {
|
||||
getRandomValues = function(arr) {
|
||||
return _crypto.getRandomValues(arr);
|
||||
};
|
||||
}
|
||||
}
|
||||
if(forge.options.usePureJavaScript ||
|
||||
(!forge.util.isNodejs && !getRandomValues)) {
|
||||
// if this is a web worker, do not use weak entropy, instead register to
|
||||
// receive strong entropy asynchronously from the main thread
|
||||
if(typeof window === 'undefined' || window.document === undefined) {
|
||||
// FIXME:
|
||||
}
|
||||
|
||||
// get load time entropy
|
||||
_ctx.collectInt(+new Date(), 32);
|
||||
|
||||
// add some entropy from navigator object
|
||||
if(typeof(navigator) !== 'undefined') {
|
||||
var _navBytes = '';
|
||||
for(var key in navigator) {
|
||||
try {
|
||||
if(typeof(navigator[key]) == 'string') {
|
||||
_navBytes += navigator[key];
|
||||
}
|
||||
} catch(e) {
|
||||
/* Some navigator keys might not be accessible, e.g. the geolocation
|
||||
attribute throws an exception if touched in Mozilla chrome://
|
||||
context.
|
||||
|
||||
Silently ignore this and just don't use this as a source of
|
||||
entropy. */
|
||||
}
|
||||
}
|
||||
_ctx.collect(_navBytes);
|
||||
_navBytes = null;
|
||||
}
|
||||
|
||||
// add mouse and keyboard collectors if jquery is available
|
||||
if(jQuery) {
|
||||
// set up mouse entropy capture
|
||||
jQuery().mousemove(function(e) {
|
||||
// add mouse coords
|
||||
_ctx.collectInt(e.clientX, 16);
|
||||
_ctx.collectInt(e.clientY, 16);
|
||||
});
|
||||
|
||||
// set up keyboard entropy capture
|
||||
jQuery().keypress(function(e) {
|
||||
_ctx.collectInt(e.charCode, 8);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Random API */
|
||||
if(!forge.random) {
|
||||
forge.random = _ctx;
|
||||
} else {
|
||||
// extend forge.random with _ctx
|
||||
for(var key in _ctx) {
|
||||
forge.random[key] = _ctx[key];
|
||||
}
|
||||
}
|
||||
|
||||
// expose spawn PRNG
|
||||
forge.random.createInstance = spawnPrng;
|
||||
|
||||
module.exports = forge.random;
|
||||
|
||||
})(typeof(jQuery) !== 'undefined' ? jQuery : null);
|
||||
|
||||
})();
|
410
node_modules/node-forge/lib/rc2.js
generated
vendored
Normal file
410
node_modules/node-forge/lib/rc2.js
generated
vendored
Normal file
@ -0,0 +1,410 @@
|
||||
/**
|
||||
* RC2 implementation.
|
||||
*
|
||||
* @author Stefan Siegl
|
||||
*
|
||||
* Copyright (c) 2012 Stefan Siegl <stesie@brokenpipe.de>
|
||||
*
|
||||
* Information on the RC2 cipher is available from RFC #2268,
|
||||
* http://www.ietf.org/rfc/rfc2268.txt
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
var piTable = [
|
||||
0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
|
||||
0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
|
||||
0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
|
||||
0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
|
||||
0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
|
||||
0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
|
||||
0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
|
||||
0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
|
||||
0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
|
||||
0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
|
||||
0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
|
||||
0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
|
||||
0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
|
||||
0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
|
||||
0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
|
||||
0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
|
||||
];
|
||||
|
||||
var s = [1, 2, 3, 5];
|
||||
|
||||
/**
|
||||
* Rotate a word left by given number of bits.
|
||||
*
|
||||
* Bits that are shifted out on the left are put back in on the right
|
||||
* hand side.
|
||||
*
|
||||
* @param word The word to shift left.
|
||||
* @param bits The number of bits to shift by.
|
||||
* @return The rotated word.
|
||||
*/
|
||||
var rol = function(word, bits) {
|
||||
return ((word << bits) & 0xffff) | ((word & 0xffff) >> (16 - bits));
|
||||
};
|
||||
|
||||
/**
|
||||
* Rotate a word right by given number of bits.
|
||||
*
|
||||
* Bits that are shifted out on the right are put back in on the left
|
||||
* hand side.
|
||||
*
|
||||
* @param word The word to shift right.
|
||||
* @param bits The number of bits to shift by.
|
||||
* @return The rotated word.
|
||||
*/
|
||||
var ror = function(word, bits) {
|
||||
return ((word & 0xffff) >> bits) | ((word << (16 - bits)) & 0xffff);
|
||||
};
|
||||
|
||||
/* RC2 API */
|
||||
module.exports = forge.rc2 = forge.rc2 || {};
|
||||
|
||||
/**
|
||||
* Perform RC2 key expansion as per RFC #2268, section 2.
|
||||
*
|
||||
* @param key variable-length user key (between 1 and 128 bytes)
|
||||
* @param effKeyBits number of effective key bits (default: 128)
|
||||
* @return the expanded RC2 key (ByteBuffer of 128 bytes)
|
||||
*/
|
||||
forge.rc2.expandKey = function(key, effKeyBits) {
|
||||
if(typeof key === 'string') {
|
||||
key = forge.util.createBuffer(key);
|
||||
}
|
||||
effKeyBits = effKeyBits || 128;
|
||||
|
||||
/* introduce variables that match the names used in RFC #2268 */
|
||||
var L = key;
|
||||
var T = key.length();
|
||||
var T1 = effKeyBits;
|
||||
var T8 = Math.ceil(T1 / 8);
|
||||
var TM = 0xff >> (T1 & 0x07);
|
||||
var i;
|
||||
|
||||
for(i = T; i < 128; i++) {
|
||||
L.putByte(piTable[(L.at(i - 1) + L.at(i - T)) & 0xff]);
|
||||
}
|
||||
|
||||
L.setAt(128 - T8, piTable[L.at(128 - T8) & TM]);
|
||||
|
||||
for(i = 127 - T8; i >= 0; i--) {
|
||||
L.setAt(i, piTable[L.at(i + 1) ^ L.at(i + T8)]);
|
||||
}
|
||||
|
||||
return L;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a RC2 cipher object.
|
||||
*
|
||||
* @param key the symmetric key to use (as base for key generation).
|
||||
* @param bits the number of effective key bits.
|
||||
* @param encrypt false for decryption, true for encryption.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
var createCipher = function(key, bits, encrypt) {
|
||||
var _finish = false, _input = null, _output = null, _iv = null;
|
||||
var mixRound, mashRound;
|
||||
var i, j, K = [];
|
||||
|
||||
/* Expand key and fill into K[] Array */
|
||||
key = forge.rc2.expandKey(key, bits);
|
||||
for(i = 0; i < 64; i++) {
|
||||
K.push(key.getInt16Le());
|
||||
}
|
||||
|
||||
if(encrypt) {
|
||||
/**
|
||||
* Perform one mixing round "in place".
|
||||
*
|
||||
* @param R Array of four words to perform mixing on.
|
||||
*/
|
||||
mixRound = function(R) {
|
||||
for(i = 0; i < 4; i++) {
|
||||
R[i] += K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) +
|
||||
((~R[(i + 3) % 4]) & R[(i + 1) % 4]);
|
||||
R[i] = rol(R[i], s[i]);
|
||||
j++;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform one mashing round "in place".
|
||||
*
|
||||
* @param R Array of four words to perform mashing on.
|
||||
*/
|
||||
mashRound = function(R) {
|
||||
for(i = 0; i < 4; i++) {
|
||||
R[i] += K[R[(i + 3) % 4] & 63];
|
||||
}
|
||||
};
|
||||
} else {
|
||||
/**
|
||||
* Perform one r-mixing round "in place".
|
||||
*
|
||||
* @param R Array of four words to perform mixing on.
|
||||
*/
|
||||
mixRound = function(R) {
|
||||
for(i = 3; i >= 0; i--) {
|
||||
R[i] = ror(R[i], s[i]);
|
||||
R[i] -= K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) +
|
||||
((~R[(i + 3) % 4]) & R[(i + 1) % 4]);
|
||||
j--;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform one r-mashing round "in place".
|
||||
*
|
||||
* @param R Array of four words to perform mashing on.
|
||||
*/
|
||||
mashRound = function(R) {
|
||||
for(i = 3; i >= 0; i--) {
|
||||
R[i] -= K[R[(i + 3) % 4] & 63];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the specified cipher execution plan.
|
||||
*
|
||||
* This function takes four words from the input buffer, applies the IV on
|
||||
* it (if requested) and runs the provided execution plan.
|
||||
*
|
||||
* The plan must be put together in form of a array of arrays. Where the
|
||||
* outer one is simply a list of steps to perform and the inner one needs
|
||||
* to have two elements: the first one telling how many rounds to perform,
|
||||
* the second one telling what to do (i.e. the function to call).
|
||||
*
|
||||
* @param {Array} plan The plan to execute.
|
||||
*/
|
||||
var runPlan = function(plan) {
|
||||
var R = [];
|
||||
|
||||
/* Get data from input buffer and fill the four words into R */
|
||||
for(i = 0; i < 4; i++) {
|
||||
var val = _input.getInt16Le();
|
||||
|
||||
if(_iv !== null) {
|
||||
if(encrypt) {
|
||||
/* We're encrypting, apply the IV first. */
|
||||
val ^= _iv.getInt16Le();
|
||||
} else {
|
||||
/* We're decryption, keep cipher text for next block. */
|
||||
_iv.putInt16Le(val);
|
||||
}
|
||||
}
|
||||
|
||||
R.push(val & 0xffff);
|
||||
}
|
||||
|
||||
/* Reset global "j" variable as per spec. */
|
||||
j = encrypt ? 0 : 63;
|
||||
|
||||
/* Run execution plan. */
|
||||
for(var ptr = 0; ptr < plan.length; ptr++) {
|
||||
for(var ctr = 0; ctr < plan[ptr][0]; ctr++) {
|
||||
plan[ptr][1](R);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write back result to output buffer. */
|
||||
for(i = 0; i < 4; i++) {
|
||||
if(_iv !== null) {
|
||||
if(encrypt) {
|
||||
/* We're encrypting in CBC-mode, feed back encrypted bytes into
|
||||
IV buffer to carry it forward to next block. */
|
||||
_iv.putInt16Le(R[i]);
|
||||
} else {
|
||||
R[i] ^= _iv.getInt16Le();
|
||||
}
|
||||
}
|
||||
|
||||
_output.putInt16Le(R[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/* Create cipher object */
|
||||
var cipher = null;
|
||||
cipher = {
|
||||
/**
|
||||
* Starts or restarts the encryption or decryption process, whichever
|
||||
* was previously configured.
|
||||
*
|
||||
* To use the cipher in CBC mode, iv may be given either as a string
|
||||
* of bytes, or as a byte buffer. For ECB mode, give null as iv.
|
||||
*
|
||||
* @param iv the initialization vector to use, null for ECB mode.
|
||||
* @param output the output the buffer to write to, null to create one.
|
||||
*/
|
||||
start: function(iv, output) {
|
||||
if(iv) {
|
||||
/* CBC mode */
|
||||
if(typeof iv === 'string') {
|
||||
iv = forge.util.createBuffer(iv);
|
||||
}
|
||||
}
|
||||
|
||||
_finish = false;
|
||||
_input = forge.util.createBuffer();
|
||||
_output = output || new forge.util.createBuffer();
|
||||
_iv = iv;
|
||||
|
||||
cipher.output = _output;
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the next block.
|
||||
*
|
||||
* @param input the buffer to read from.
|
||||
*/
|
||||
update: function(input) {
|
||||
if(!_finish) {
|
||||
// not finishing, so fill the input buffer with more input
|
||||
_input.putBuffer(input);
|
||||
}
|
||||
|
||||
while(_input.length() >= 8) {
|
||||
runPlan([
|
||||
[ 5, mixRound ],
|
||||
[ 1, mashRound ],
|
||||
[ 6, mixRound ],
|
||||
[ 1, mashRound ],
|
||||
[ 5, mixRound ]
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Finishes encrypting or decrypting.
|
||||
*
|
||||
* @param pad a padding function to use, null for PKCS#7 padding,
|
||||
* signature(blockSize, buffer, decrypt).
|
||||
*
|
||||
* @return true if successful, false on error.
|
||||
*/
|
||||
finish: function(pad) {
|
||||
var rval = true;
|
||||
|
||||
if(encrypt) {
|
||||
if(pad) {
|
||||
rval = pad(8, _input, !encrypt);
|
||||
} else {
|
||||
// add PKCS#7 padding to block (each pad byte is the
|
||||
// value of the number of pad bytes)
|
||||
var padding = (_input.length() === 8) ? 8 : (8 - _input.length());
|
||||
_input.fillWithByte(padding, padding);
|
||||
}
|
||||
}
|
||||
|
||||
if(rval) {
|
||||
// do final update
|
||||
_finish = true;
|
||||
cipher.update();
|
||||
}
|
||||
|
||||
if(!encrypt) {
|
||||
// check for error: input data not a multiple of block size
|
||||
rval = (_input.length() === 0);
|
||||
if(rval) {
|
||||
if(pad) {
|
||||
rval = pad(8, _output, !encrypt);
|
||||
} else {
|
||||
// ensure padding byte count is valid
|
||||
var len = _output.length();
|
||||
var count = _output.at(len - 1);
|
||||
|
||||
if(count > len) {
|
||||
rval = false;
|
||||
} else {
|
||||
// trim off padding bytes
|
||||
_output.truncate(count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
};
|
||||
|
||||
return cipher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the
|
||||
* given symmetric key. The output will be stored in the 'output' member
|
||||
* of the returned cipher.
|
||||
*
|
||||
* The key and iv may be given as a string of bytes or a byte buffer.
|
||||
* The cipher is initialized to use 128 effective key bits.
|
||||
*
|
||||
* @param key the symmetric key to use.
|
||||
* @param iv the initialization vector to use.
|
||||
* @param output the buffer to write to, null to create one.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.rc2.startEncrypting = function(key, iv, output) {
|
||||
var cipher = forge.rc2.createEncryptionCipher(key, 128);
|
||||
cipher.start(iv, output);
|
||||
return cipher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an RC2 cipher object to encrypt data in ECB or CBC mode using the
|
||||
* given symmetric key.
|
||||
*
|
||||
* The key may be given as a string of bytes or a byte buffer.
|
||||
*
|
||||
* To start encrypting call start() on the cipher with an iv and optional
|
||||
* output buffer.
|
||||
*
|
||||
* @param key the symmetric key to use.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.rc2.createEncryptionCipher = function(key, bits) {
|
||||
return createCipher(key, bits, true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the
|
||||
* given symmetric key. The output will be stored in the 'output' member
|
||||
* of the returned cipher.
|
||||
*
|
||||
* The key and iv may be given as a string of bytes or a byte buffer.
|
||||
* The cipher is initialized to use 128 effective key bits.
|
||||
*
|
||||
* @param key the symmetric key to use.
|
||||
* @param iv the initialization vector to use.
|
||||
* @param output the buffer to write to, null to create one.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.rc2.startDecrypting = function(key, iv, output) {
|
||||
var cipher = forge.rc2.createDecryptionCipher(key, 128);
|
||||
cipher.start(iv, output);
|
||||
return cipher;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an RC2 cipher object to decrypt data in ECB or CBC mode using the
|
||||
* given symmetric key.
|
||||
*
|
||||
* The key may be given as a string of bytes or a byte buffer.
|
||||
*
|
||||
* To start decrypting call start() on the cipher with an iv and optional
|
||||
* output buffer.
|
||||
*
|
||||
* @param key the symmetric key to use.
|
||||
*
|
||||
* @return the cipher.
|
||||
*/
|
||||
forge.rc2.createDecryptionCipher = function(key, bits) {
|
||||
return createCipher(key, bits, false);
|
||||
};
|
1796
node_modules/node-forge/lib/rsa.js
generated
vendored
Normal file
1796
node_modules/node-forge/lib/rsa.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
319
node_modules/node-forge/lib/sha1.js
generated
vendored
Normal file
319
node_modules/node-forge/lib/sha1.js
generated
vendored
Normal file
@ -0,0 +1,319 @@
|
||||
/**
|
||||
* Secure Hash Algorithm with 160-bit digest (SHA-1) implementation.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2015 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
var sha1 = module.exports = forge.sha1 = forge.sha1 || {};
|
||||
forge.md.sha1 = forge.md.algorithms.sha1 = sha1;
|
||||
|
||||
/**
|
||||
* Creates a SHA-1 message digest object.
|
||||
*
|
||||
* @return a message digest object.
|
||||
*/
|
||||
sha1.create = function() {
|
||||
// do initialization as necessary
|
||||
if(!_initialized) {
|
||||
_init();
|
||||
}
|
||||
|
||||
// SHA-1 state contains five 32-bit integers
|
||||
var _state = null;
|
||||
|
||||
// input buffer
|
||||
var _input = forge.util.createBuffer();
|
||||
|
||||
// used for word storage
|
||||
var _w = new Array(80);
|
||||
|
||||
// message digest object
|
||||
var md = {
|
||||
algorithm: 'sha1',
|
||||
blockLength: 64,
|
||||
digestLength: 20,
|
||||
// 56-bit length of message so far (does not including padding)
|
||||
messageLength: 0,
|
||||
// true message length
|
||||
fullMessageLength: null,
|
||||
// size of message length in bytes
|
||||
messageLengthSize: 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the digest.
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.start = function() {
|
||||
// up to 56-bit message length for convenience
|
||||
md.messageLength = 0;
|
||||
|
||||
// full message length (set md.messageLength64 for backwards-compatibility)
|
||||
md.fullMessageLength = md.messageLength64 = [];
|
||||
var int32s = md.messageLengthSize / 4;
|
||||
for(var i = 0; i < int32s; ++i) {
|
||||
md.fullMessageLength.push(0);
|
||||
}
|
||||
_input = forge.util.createBuffer();
|
||||
_state = {
|
||||
h0: 0x67452301,
|
||||
h1: 0xEFCDAB89,
|
||||
h2: 0x98BADCFE,
|
||||
h3: 0x10325476,
|
||||
h4: 0xC3D2E1F0
|
||||
};
|
||||
return md;
|
||||
};
|
||||
// start digest automatically for first time
|
||||
md.start();
|
||||
|
||||
/**
|
||||
* Updates the digest with the given message input. The given input can
|
||||
* treated as raw input (no encoding will be applied) or an encoding of
|
||||
* 'utf8' maybe given to encode the input using UTF-8.
|
||||
*
|
||||
* @param msg the message input to update with.
|
||||
* @param encoding the encoding to use (default: 'raw', other: 'utf8').
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.update = function(msg, encoding) {
|
||||
if(encoding === 'utf8') {
|
||||
msg = forge.util.encodeUtf8(msg);
|
||||
}
|
||||
|
||||
// update message length
|
||||
var len = msg.length;
|
||||
md.messageLength += len;
|
||||
len = [(len / 0x100000000) >>> 0, len >>> 0];
|
||||
for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
|
||||
md.fullMessageLength[i] += len[1];
|
||||
len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
|
||||
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
|
||||
len[0] = ((len[1] / 0x100000000) >>> 0);
|
||||
}
|
||||
|
||||
// add bytes to input buffer
|
||||
_input.putBytes(msg);
|
||||
|
||||
// process bytes
|
||||
_update(_state, _w, _input);
|
||||
|
||||
// compact input buffer every 2K or if empty
|
||||
if(_input.read > 2048 || _input.length() === 0) {
|
||||
_input.compact();
|
||||
}
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
/**
|
||||
* Produces the digest.
|
||||
*
|
||||
* @return a byte buffer containing the digest value.
|
||||
*/
|
||||
md.digest = function() {
|
||||
/* Note: Here we copy the remaining bytes in the input buffer and
|
||||
add the appropriate SHA-1 padding. Then we do the final update
|
||||
on a copy of the state so that if the user wants to get
|
||||
intermediate digests they can do so. */
|
||||
|
||||
/* Determine the number of bytes that must be added to the message
|
||||
to ensure its length is congruent to 448 mod 512. In other words,
|
||||
the data to be digested must be a multiple of 512 bits (or 128 bytes).
|
||||
This data includes the message, some padding, and the length of the
|
||||
message. Since the length of the message will be encoded as 8 bytes (64
|
||||
bits), that means that the last segment of the data must have 56 bytes
|
||||
(448 bits) of message and padding. Therefore, the length of the message
|
||||
plus the padding must be congruent to 448 mod 512 because
|
||||
512 - 128 = 448.
|
||||
|
||||
In order to fill up the message length it must be filled with
|
||||
padding that begins with 1 bit followed by all 0 bits. Padding
|
||||
must *always* be present, so if the message length is already
|
||||
congruent to 448 mod 512, then 512 padding bits must be added. */
|
||||
|
||||
var finalBlock = forge.util.createBuffer();
|
||||
finalBlock.putBytes(_input.bytes());
|
||||
|
||||
// compute remaining size to be digested (include message length size)
|
||||
var remaining = (
|
||||
md.fullMessageLength[md.fullMessageLength.length - 1] +
|
||||
md.messageLengthSize);
|
||||
|
||||
// add padding for overflow blockSize - overflow
|
||||
// _padding starts with 1 byte with first bit is set (byte value 128), then
|
||||
// there may be up to (blockSize - 1) other pad bytes
|
||||
var overflow = remaining & (md.blockLength - 1);
|
||||
finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
|
||||
|
||||
// serialize message length in bits in big-endian order; since length
|
||||
// is stored in bytes we multiply by 8 and add carry from next int
|
||||
var next, carry;
|
||||
var bits = md.fullMessageLength[0] * 8;
|
||||
for(var i = 0; i < md.fullMessageLength.length - 1; ++i) {
|
||||
next = md.fullMessageLength[i + 1] * 8;
|
||||
carry = (next / 0x100000000) >>> 0;
|
||||
bits += carry;
|
||||
finalBlock.putInt32(bits >>> 0);
|
||||
bits = next >>> 0;
|
||||
}
|
||||
finalBlock.putInt32(bits);
|
||||
|
||||
var s2 = {
|
||||
h0: _state.h0,
|
||||
h1: _state.h1,
|
||||
h2: _state.h2,
|
||||
h3: _state.h3,
|
||||
h4: _state.h4
|
||||
};
|
||||
_update(s2, _w, finalBlock);
|
||||
var rval = forge.util.createBuffer();
|
||||
rval.putInt32(s2.h0);
|
||||
rval.putInt32(s2.h1);
|
||||
rval.putInt32(s2.h2);
|
||||
rval.putInt32(s2.h3);
|
||||
rval.putInt32(s2.h4);
|
||||
return rval;
|
||||
};
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
// sha-1 padding bytes not initialized yet
|
||||
var _padding = null;
|
||||
var _initialized = false;
|
||||
|
||||
/**
|
||||
* Initializes the constant tables.
|
||||
*/
|
||||
function _init() {
|
||||
// create padding
|
||||
_padding = String.fromCharCode(128);
|
||||
_padding += forge.util.fillString(String.fromCharCode(0x00), 64);
|
||||
|
||||
// now initialized
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a SHA-1 state with the given byte buffer.
|
||||
*
|
||||
* @param s the SHA-1 state to update.
|
||||
* @param w the array to use to store words.
|
||||
* @param bytes the byte buffer to update with.
|
||||
*/
|
||||
function _update(s, w, bytes) {
|
||||
// consume 512 bit (64 byte) chunks
|
||||
var t, a, b, c, d, e, f, i;
|
||||
var len = bytes.length();
|
||||
while(len >= 64) {
|
||||
// the w array will be populated with sixteen 32-bit big-endian words
|
||||
// and then extended into 80 32-bit words according to SHA-1 algorithm
|
||||
// and for 32-79 using Max Locktyukhin's optimization
|
||||
|
||||
// initialize hash value for this chunk
|
||||
a = s.h0;
|
||||
b = s.h1;
|
||||
c = s.h2;
|
||||
d = s.h3;
|
||||
e = s.h4;
|
||||
|
||||
// round 1
|
||||
for(i = 0; i < 16; ++i) {
|
||||
t = bytes.getInt32();
|
||||
w[i] = t;
|
||||
f = d ^ (b & (c ^ d));
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
for(; i < 20; ++i) {
|
||||
t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]);
|
||||
t = (t << 1) | (t >>> 31);
|
||||
w[i] = t;
|
||||
f = d ^ (b & (c ^ d));
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
// round 2
|
||||
for(; i < 32; ++i) {
|
||||
t = (w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]);
|
||||
t = (t << 1) | (t >>> 31);
|
||||
w[i] = t;
|
||||
f = b ^ c ^ d;
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
for(; i < 40; ++i) {
|
||||
t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]);
|
||||
t = (t << 2) | (t >>> 30);
|
||||
w[i] = t;
|
||||
f = b ^ c ^ d;
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
// round 3
|
||||
for(; i < 60; ++i) {
|
||||
t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]);
|
||||
t = (t << 2) | (t >>> 30);
|
||||
w[i] = t;
|
||||
f = (b & c) | (d & (b ^ c));
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0x8F1BBCDC + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
// round 4
|
||||
for(; i < 80; ++i) {
|
||||
t = (w[i - 6] ^ w[i - 16] ^ w[i - 28] ^ w[i - 32]);
|
||||
t = (t << 2) | (t >>> 30);
|
||||
w[i] = t;
|
||||
f = b ^ c ^ d;
|
||||
t = ((a << 5) | (a >>> 27)) + f + e + 0xCA62C1D6 + t;
|
||||
e = d;
|
||||
d = c;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
c = ((b << 30) | (b >>> 2)) >>> 0;
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
// update hash state
|
||||
s.h0 = (s.h0 + a) | 0;
|
||||
s.h1 = (s.h1 + b) | 0;
|
||||
s.h2 = (s.h2 + c) | 0;
|
||||
s.h3 = (s.h3 + d) | 0;
|
||||
s.h4 = (s.h4 + e) | 0;
|
||||
|
||||
len -= 64;
|
||||
}
|
||||
}
|
327
node_modules/node-forge/lib/sha256.js
generated
vendored
Normal file
327
node_modules/node-forge/lib/sha256.js
generated
vendored
Normal file
@ -0,0 +1,327 @@
|
||||
/**
|
||||
* Secure Hash Algorithm with 256-bit digest (SHA-256) implementation.
|
||||
*
|
||||
* See FIPS 180-2 for details.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2015 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
var sha256 = module.exports = forge.sha256 = forge.sha256 || {};
|
||||
forge.md.sha256 = forge.md.algorithms.sha256 = sha256;
|
||||
|
||||
/**
|
||||
* Creates a SHA-256 message digest object.
|
||||
*
|
||||
* @return a message digest object.
|
||||
*/
|
||||
sha256.create = function() {
|
||||
// do initialization as necessary
|
||||
if(!_initialized) {
|
||||
_init();
|
||||
}
|
||||
|
||||
// SHA-256 state contains eight 32-bit integers
|
||||
var _state = null;
|
||||
|
||||
// input buffer
|
||||
var _input = forge.util.createBuffer();
|
||||
|
||||
// used for word storage
|
||||
var _w = new Array(64);
|
||||
|
||||
// message digest object
|
||||
var md = {
|
||||
algorithm: 'sha256',
|
||||
blockLength: 64,
|
||||
digestLength: 32,
|
||||
// 56-bit length of message so far (does not including padding)
|
||||
messageLength: 0,
|
||||
// true message length
|
||||
fullMessageLength: null,
|
||||
// size of message length in bytes
|
||||
messageLengthSize: 8
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the digest.
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.start = function() {
|
||||
// up to 56-bit message length for convenience
|
||||
md.messageLength = 0;
|
||||
|
||||
// full message length (set md.messageLength64 for backwards-compatibility)
|
||||
md.fullMessageLength = md.messageLength64 = [];
|
||||
var int32s = md.messageLengthSize / 4;
|
||||
for(var i = 0; i < int32s; ++i) {
|
||||
md.fullMessageLength.push(0);
|
||||
}
|
||||
_input = forge.util.createBuffer();
|
||||
_state = {
|
||||
h0: 0x6A09E667,
|
||||
h1: 0xBB67AE85,
|
||||
h2: 0x3C6EF372,
|
||||
h3: 0xA54FF53A,
|
||||
h4: 0x510E527F,
|
||||
h5: 0x9B05688C,
|
||||
h6: 0x1F83D9AB,
|
||||
h7: 0x5BE0CD19
|
||||
};
|
||||
return md;
|
||||
};
|
||||
// start digest automatically for first time
|
||||
md.start();
|
||||
|
||||
/**
|
||||
* Updates the digest with the given message input. The given input can
|
||||
* treated as raw input (no encoding will be applied) or an encoding of
|
||||
* 'utf8' maybe given to encode the input using UTF-8.
|
||||
*
|
||||
* @param msg the message input to update with.
|
||||
* @param encoding the encoding to use (default: 'raw', other: 'utf8').
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.update = function(msg, encoding) {
|
||||
if(encoding === 'utf8') {
|
||||
msg = forge.util.encodeUtf8(msg);
|
||||
}
|
||||
|
||||
// update message length
|
||||
var len = msg.length;
|
||||
md.messageLength += len;
|
||||
len = [(len / 0x100000000) >>> 0, len >>> 0];
|
||||
for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
|
||||
md.fullMessageLength[i] += len[1];
|
||||
len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
|
||||
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
|
||||
len[0] = ((len[1] / 0x100000000) >>> 0);
|
||||
}
|
||||
|
||||
// add bytes to input buffer
|
||||
_input.putBytes(msg);
|
||||
|
||||
// process bytes
|
||||
_update(_state, _w, _input);
|
||||
|
||||
// compact input buffer every 2K or if empty
|
||||
if(_input.read > 2048 || _input.length() === 0) {
|
||||
_input.compact();
|
||||
}
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
/**
|
||||
* Produces the digest.
|
||||
*
|
||||
* @return a byte buffer containing the digest value.
|
||||
*/
|
||||
md.digest = function() {
|
||||
/* Note: Here we copy the remaining bytes in the input buffer and
|
||||
add the appropriate SHA-256 padding. Then we do the final update
|
||||
on a copy of the state so that if the user wants to get
|
||||
intermediate digests they can do so. */
|
||||
|
||||
/* Determine the number of bytes that must be added to the message
|
||||
to ensure its length is congruent to 448 mod 512. In other words,
|
||||
the data to be digested must be a multiple of 512 bits (or 128 bytes).
|
||||
This data includes the message, some padding, and the length of the
|
||||
message. Since the length of the message will be encoded as 8 bytes (64
|
||||
bits), that means that the last segment of the data must have 56 bytes
|
||||
(448 bits) of message and padding. Therefore, the length of the message
|
||||
plus the padding must be congruent to 448 mod 512 because
|
||||
512 - 128 = 448.
|
||||
|
||||
In order to fill up the message length it must be filled with
|
||||
padding that begins with 1 bit followed by all 0 bits. Padding
|
||||
must *always* be present, so if the message length is already
|
||||
congruent to 448 mod 512, then 512 padding bits must be added. */
|
||||
|
||||
var finalBlock = forge.util.createBuffer();
|
||||
finalBlock.putBytes(_input.bytes());
|
||||
|
||||
// compute remaining size to be digested (include message length size)
|
||||
var remaining = (
|
||||
md.fullMessageLength[md.fullMessageLength.length - 1] +
|
||||
md.messageLengthSize);
|
||||
|
||||
// add padding for overflow blockSize - overflow
|
||||
// _padding starts with 1 byte with first bit is set (byte value 128), then
|
||||
// there may be up to (blockSize - 1) other pad bytes
|
||||
var overflow = remaining & (md.blockLength - 1);
|
||||
finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
|
||||
|
||||
// serialize message length in bits in big-endian order; since length
|
||||
// is stored in bytes we multiply by 8 and add carry from next int
|
||||
var next, carry;
|
||||
var bits = md.fullMessageLength[0] * 8;
|
||||
for(var i = 0; i < md.fullMessageLength.length - 1; ++i) {
|
||||
next = md.fullMessageLength[i + 1] * 8;
|
||||
carry = (next / 0x100000000) >>> 0;
|
||||
bits += carry;
|
||||
finalBlock.putInt32(bits >>> 0);
|
||||
bits = next >>> 0;
|
||||
}
|
||||
finalBlock.putInt32(bits);
|
||||
|
||||
var s2 = {
|
||||
h0: _state.h0,
|
||||
h1: _state.h1,
|
||||
h2: _state.h2,
|
||||
h3: _state.h3,
|
||||
h4: _state.h4,
|
||||
h5: _state.h5,
|
||||
h6: _state.h6,
|
||||
h7: _state.h7
|
||||
};
|
||||
_update(s2, _w, finalBlock);
|
||||
var rval = forge.util.createBuffer();
|
||||
rval.putInt32(s2.h0);
|
||||
rval.putInt32(s2.h1);
|
||||
rval.putInt32(s2.h2);
|
||||
rval.putInt32(s2.h3);
|
||||
rval.putInt32(s2.h4);
|
||||
rval.putInt32(s2.h5);
|
||||
rval.putInt32(s2.h6);
|
||||
rval.putInt32(s2.h7);
|
||||
return rval;
|
||||
};
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
// sha-256 padding bytes not initialized yet
|
||||
var _padding = null;
|
||||
var _initialized = false;
|
||||
|
||||
// table of constants
|
||||
var _k = null;
|
||||
|
||||
/**
|
||||
* Initializes the constant tables.
|
||||
*/
|
||||
function _init() {
|
||||
// create padding
|
||||
_padding = String.fromCharCode(128);
|
||||
_padding += forge.util.fillString(String.fromCharCode(0x00), 64);
|
||||
|
||||
// create K table for SHA-256
|
||||
_k = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
|
||||
|
||||
// now initialized
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a SHA-256 state with the given byte buffer.
|
||||
*
|
||||
* @param s the SHA-256 state to update.
|
||||
* @param w the array to use to store words.
|
||||
* @param bytes the byte buffer to update with.
|
||||
*/
|
||||
function _update(s, w, bytes) {
|
||||
// consume 512 bit (64 byte) chunks
|
||||
var t1, t2, s0, s1, ch, maj, i, a, b, c, d, e, f, g, h;
|
||||
var len = bytes.length();
|
||||
while(len >= 64) {
|
||||
// the w array will be populated with sixteen 32-bit big-endian words
|
||||
// and then extended into 64 32-bit words according to SHA-256
|
||||
for(i = 0; i < 16; ++i) {
|
||||
w[i] = bytes.getInt32();
|
||||
}
|
||||
for(; i < 64; ++i) {
|
||||
// XOR word 2 words ago rot right 17, rot right 19, shft right 10
|
||||
t1 = w[i - 2];
|
||||
t1 =
|
||||
((t1 >>> 17) | (t1 << 15)) ^
|
||||
((t1 >>> 19) | (t1 << 13)) ^
|
||||
(t1 >>> 10);
|
||||
// XOR word 15 words ago rot right 7, rot right 18, shft right 3
|
||||
t2 = w[i - 15];
|
||||
t2 =
|
||||
((t2 >>> 7) | (t2 << 25)) ^
|
||||
((t2 >>> 18) | (t2 << 14)) ^
|
||||
(t2 >>> 3);
|
||||
// sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32
|
||||
w[i] = (t1 + w[i - 7] + t2 + w[i - 16]) | 0;
|
||||
}
|
||||
|
||||
// initialize hash value for this chunk
|
||||
a = s.h0;
|
||||
b = s.h1;
|
||||
c = s.h2;
|
||||
d = s.h3;
|
||||
e = s.h4;
|
||||
f = s.h5;
|
||||
g = s.h6;
|
||||
h = s.h7;
|
||||
|
||||
// round function
|
||||
for(i = 0; i < 64; ++i) {
|
||||
// Sum1(e)
|
||||
s1 =
|
||||
((e >>> 6) | (e << 26)) ^
|
||||
((e >>> 11) | (e << 21)) ^
|
||||
((e >>> 25) | (e << 7));
|
||||
// Ch(e, f, g) (optimized the same way as SHA-1)
|
||||
ch = g ^ (e & (f ^ g));
|
||||
// Sum0(a)
|
||||
s0 =
|
||||
((a >>> 2) | (a << 30)) ^
|
||||
((a >>> 13) | (a << 19)) ^
|
||||
((a >>> 22) | (a << 10));
|
||||
// Maj(a, b, c) (optimized the same way as SHA-1)
|
||||
maj = (a & b) | (c & (a ^ b));
|
||||
|
||||
// main algorithm
|
||||
t1 = h + s1 + ch + _k[i] + w[i];
|
||||
t2 = s0 + maj;
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
// can't truncate with `| 0`
|
||||
e = (d + t1) >>> 0;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
// `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
|
||||
// can't truncate with `| 0`
|
||||
a = (t1 + t2) >>> 0;
|
||||
}
|
||||
|
||||
// update hash state
|
||||
s.h0 = (s.h0 + a) | 0;
|
||||
s.h1 = (s.h1 + b) | 0;
|
||||
s.h2 = (s.h2 + c) | 0;
|
||||
s.h3 = (s.h3 + d) | 0;
|
||||
s.h4 = (s.h4 + e) | 0;
|
||||
s.h5 = (s.h5 + f) | 0;
|
||||
s.h6 = (s.h6 + g) | 0;
|
||||
s.h7 = (s.h7 + h) | 0;
|
||||
len -= 64;
|
||||
}
|
||||
}
|
561
node_modules/node-forge/lib/sha512.js
generated
vendored
Normal file
561
node_modules/node-forge/lib/sha512.js
generated
vendored
Normal file
@ -0,0 +1,561 @@
|
||||
/**
|
||||
* Secure Hash Algorithm with a 1024-bit block size implementation.
|
||||
*
|
||||
* This includes: SHA-512, SHA-384, SHA-512/224, and SHA-512/256. For
|
||||
* SHA-256 (block size 512 bits), see sha256.js.
|
||||
*
|
||||
* See FIPS 180-4 for details.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2014-2015 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./md');
|
||||
require('./util');
|
||||
|
||||
var sha512 = module.exports = forge.sha512 = forge.sha512 || {};
|
||||
|
||||
// SHA-512
|
||||
forge.md.sha512 = forge.md.algorithms.sha512 = sha512;
|
||||
|
||||
// SHA-384
|
||||
var sha384 = forge.sha384 = forge.sha512.sha384 = forge.sha512.sha384 || {};
|
||||
sha384.create = function() {
|
||||
return sha512.create('SHA-384');
|
||||
};
|
||||
forge.md.sha384 = forge.md.algorithms.sha384 = sha384;
|
||||
|
||||
// SHA-512/256
|
||||
forge.sha512.sha256 = forge.sha512.sha256 || {
|
||||
create: function() {
|
||||
return sha512.create('SHA-512/256');
|
||||
}
|
||||
};
|
||||
forge.md['sha512/256'] = forge.md.algorithms['sha512/256'] =
|
||||
forge.sha512.sha256;
|
||||
|
||||
// SHA-512/224
|
||||
forge.sha512.sha224 = forge.sha512.sha224 || {
|
||||
create: function() {
|
||||
return sha512.create('SHA-512/224');
|
||||
}
|
||||
};
|
||||
forge.md['sha512/224'] = forge.md.algorithms['sha512/224'] =
|
||||
forge.sha512.sha224;
|
||||
|
||||
/**
|
||||
* Creates a SHA-2 message digest object.
|
||||
*
|
||||
* @param algorithm the algorithm to use (SHA-512, SHA-384, SHA-512/224,
|
||||
* SHA-512/256).
|
||||
*
|
||||
* @return a message digest object.
|
||||
*/
|
||||
sha512.create = function(algorithm) {
|
||||
// do initialization as necessary
|
||||
if(!_initialized) {
|
||||
_init();
|
||||
}
|
||||
|
||||
if(typeof algorithm === 'undefined') {
|
||||
algorithm = 'SHA-512';
|
||||
}
|
||||
|
||||
if(!(algorithm in _states)) {
|
||||
throw new Error('Invalid SHA-512 algorithm: ' + algorithm);
|
||||
}
|
||||
|
||||
// SHA-512 state contains eight 64-bit integers (each as two 32-bit ints)
|
||||
var _state = _states[algorithm];
|
||||
var _h = null;
|
||||
|
||||
// input buffer
|
||||
var _input = forge.util.createBuffer();
|
||||
|
||||
// used for 64-bit word storage
|
||||
var _w = new Array(80);
|
||||
for(var wi = 0; wi < 80; ++wi) {
|
||||
_w[wi] = new Array(2);
|
||||
}
|
||||
|
||||
// determine digest length by algorithm name (default)
|
||||
var digestLength = 64;
|
||||
switch (algorithm) {
|
||||
case 'SHA-384':
|
||||
digestLength = 48;
|
||||
break;
|
||||
case 'SHA-512/256':
|
||||
digestLength = 32;
|
||||
break;
|
||||
case 'SHA-512/224':
|
||||
digestLength = 28;
|
||||
break;
|
||||
}
|
||||
|
||||
// message digest object
|
||||
var md = {
|
||||
// SHA-512 => sha512
|
||||
algorithm: algorithm.replace('-', '').toLowerCase(),
|
||||
blockLength: 128,
|
||||
digestLength: digestLength,
|
||||
// 56-bit length of message so far (does not including padding)
|
||||
messageLength: 0,
|
||||
// true message length
|
||||
fullMessageLength: null,
|
||||
// size of message length in bytes
|
||||
messageLengthSize: 16
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the digest.
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.start = function() {
|
||||
// up to 56-bit message length for convenience
|
||||
md.messageLength = 0;
|
||||
|
||||
// full message length (set md.messageLength128 for backwards-compatibility)
|
||||
md.fullMessageLength = md.messageLength128 = [];
|
||||
var int32s = md.messageLengthSize / 4;
|
||||
for(var i = 0; i < int32s; ++i) {
|
||||
md.fullMessageLength.push(0);
|
||||
}
|
||||
_input = forge.util.createBuffer();
|
||||
_h = new Array(_state.length);
|
||||
for(var i = 0; i < _state.length; ++i) {
|
||||
_h[i] = _state[i].slice(0);
|
||||
}
|
||||
return md;
|
||||
};
|
||||
// start digest automatically for first time
|
||||
md.start();
|
||||
|
||||
/**
|
||||
* Updates the digest with the given message input. The given input can
|
||||
* treated as raw input (no encoding will be applied) or an encoding of
|
||||
* 'utf8' maybe given to encode the input using UTF-8.
|
||||
*
|
||||
* @param msg the message input to update with.
|
||||
* @param encoding the encoding to use (default: 'raw', other: 'utf8').
|
||||
*
|
||||
* @return this digest object.
|
||||
*/
|
||||
md.update = function(msg, encoding) {
|
||||
if(encoding === 'utf8') {
|
||||
msg = forge.util.encodeUtf8(msg);
|
||||
}
|
||||
|
||||
// update message length
|
||||
var len = msg.length;
|
||||
md.messageLength += len;
|
||||
len = [(len / 0x100000000) >>> 0, len >>> 0];
|
||||
for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
|
||||
md.fullMessageLength[i] += len[1];
|
||||
len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
|
||||
md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
|
||||
len[0] = ((len[1] / 0x100000000) >>> 0);
|
||||
}
|
||||
|
||||
// add bytes to input buffer
|
||||
_input.putBytes(msg);
|
||||
|
||||
// process bytes
|
||||
_update(_h, _w, _input);
|
||||
|
||||
// compact input buffer every 2K or if empty
|
||||
if(_input.read > 2048 || _input.length() === 0) {
|
||||
_input.compact();
|
||||
}
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
/**
|
||||
* Produces the digest.
|
||||
*
|
||||
* @return a byte buffer containing the digest value.
|
||||
*/
|
||||
md.digest = function() {
|
||||
/* Note: Here we copy the remaining bytes in the input buffer and
|
||||
add the appropriate SHA-512 padding. Then we do the final update
|
||||
on a copy of the state so that if the user wants to get
|
||||
intermediate digests they can do so. */
|
||||
|
||||
/* Determine the number of bytes that must be added to the message
|
||||
to ensure its length is congruent to 896 mod 1024. In other words,
|
||||
the data to be digested must be a multiple of 1024 bits (or 128 bytes).
|
||||
This data includes the message, some padding, and the length of the
|
||||
message. Since the length of the message will be encoded as 16 bytes (128
|
||||
bits), that means that the last segment of the data must have 112 bytes
|
||||
(896 bits) of message and padding. Therefore, the length of the message
|
||||
plus the padding must be congruent to 896 mod 1024 because
|
||||
1024 - 128 = 896.
|
||||
|
||||
In order to fill up the message length it must be filled with
|
||||
padding that begins with 1 bit followed by all 0 bits. Padding
|
||||
must *always* be present, so if the message length is already
|
||||
congruent to 896 mod 1024, then 1024 padding bits must be added. */
|
||||
|
||||
var finalBlock = forge.util.createBuffer();
|
||||
finalBlock.putBytes(_input.bytes());
|
||||
|
||||
// compute remaining size to be digested (include message length size)
|
||||
var remaining = (
|
||||
md.fullMessageLength[md.fullMessageLength.length - 1] +
|
||||
md.messageLengthSize);
|
||||
|
||||
// add padding for overflow blockSize - overflow
|
||||
// _padding starts with 1 byte with first bit is set (byte value 128), then
|
||||
// there may be up to (blockSize - 1) other pad bytes
|
||||
var overflow = remaining & (md.blockLength - 1);
|
||||
finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
|
||||
|
||||
// serialize message length in bits in big-endian order; since length
|
||||
// is stored in bytes we multiply by 8 and add carry from next int
|
||||
var next, carry;
|
||||
var bits = md.fullMessageLength[0] * 8;
|
||||
for(var i = 0; i < md.fullMessageLength.length - 1; ++i) {
|
||||
next = md.fullMessageLength[i + 1] * 8;
|
||||
carry = (next / 0x100000000) >>> 0;
|
||||
bits += carry;
|
||||
finalBlock.putInt32(bits >>> 0);
|
||||
bits = next >>> 0;
|
||||
}
|
||||
finalBlock.putInt32(bits);
|
||||
|
||||
var h = new Array(_h.length);
|
||||
for(var i = 0; i < _h.length; ++i) {
|
||||
h[i] = _h[i].slice(0);
|
||||
}
|
||||
_update(h, _w, finalBlock);
|
||||
var rval = forge.util.createBuffer();
|
||||
var hlen;
|
||||
if(algorithm === 'SHA-512') {
|
||||
hlen = h.length;
|
||||
} else if(algorithm === 'SHA-384') {
|
||||
hlen = h.length - 2;
|
||||
} else {
|
||||
hlen = h.length - 4;
|
||||
}
|
||||
for(var i = 0; i < hlen; ++i) {
|
||||
rval.putInt32(h[i][0]);
|
||||
if(i !== hlen - 1 || algorithm !== 'SHA-512/224') {
|
||||
rval.putInt32(h[i][1]);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
return md;
|
||||
};
|
||||
|
||||
// sha-512 padding bytes not initialized yet
|
||||
var _padding = null;
|
||||
var _initialized = false;
|
||||
|
||||
// table of constants
|
||||
var _k = null;
|
||||
|
||||
// initial hash states
|
||||
var _states = null;
|
||||
|
||||
/**
|
||||
* Initializes the constant tables.
|
||||
*/
|
||||
function _init() {
|
||||
// create padding
|
||||
_padding = String.fromCharCode(128);
|
||||
_padding += forge.util.fillString(String.fromCharCode(0x00), 128);
|
||||
|
||||
// create K table for SHA-512
|
||||
_k = [
|
||||
[0x428a2f98, 0xd728ae22], [0x71374491, 0x23ef65cd],
|
||||
[0xb5c0fbcf, 0xec4d3b2f], [0xe9b5dba5, 0x8189dbbc],
|
||||
[0x3956c25b, 0xf348b538], [0x59f111f1, 0xb605d019],
|
||||
[0x923f82a4, 0xaf194f9b], [0xab1c5ed5, 0xda6d8118],
|
||||
[0xd807aa98, 0xa3030242], [0x12835b01, 0x45706fbe],
|
||||
[0x243185be, 0x4ee4b28c], [0x550c7dc3, 0xd5ffb4e2],
|
||||
[0x72be5d74, 0xf27b896f], [0x80deb1fe, 0x3b1696b1],
|
||||
[0x9bdc06a7, 0x25c71235], [0xc19bf174, 0xcf692694],
|
||||
[0xe49b69c1, 0x9ef14ad2], [0xefbe4786, 0x384f25e3],
|
||||
[0x0fc19dc6, 0x8b8cd5b5], [0x240ca1cc, 0x77ac9c65],
|
||||
[0x2de92c6f, 0x592b0275], [0x4a7484aa, 0x6ea6e483],
|
||||
[0x5cb0a9dc, 0xbd41fbd4], [0x76f988da, 0x831153b5],
|
||||
[0x983e5152, 0xee66dfab], [0xa831c66d, 0x2db43210],
|
||||
[0xb00327c8, 0x98fb213f], [0xbf597fc7, 0xbeef0ee4],
|
||||
[0xc6e00bf3, 0x3da88fc2], [0xd5a79147, 0x930aa725],
|
||||
[0x06ca6351, 0xe003826f], [0x14292967, 0x0a0e6e70],
|
||||
[0x27b70a85, 0x46d22ffc], [0x2e1b2138, 0x5c26c926],
|
||||
[0x4d2c6dfc, 0x5ac42aed], [0x53380d13, 0x9d95b3df],
|
||||
[0x650a7354, 0x8baf63de], [0x766a0abb, 0x3c77b2a8],
|
||||
[0x81c2c92e, 0x47edaee6], [0x92722c85, 0x1482353b],
|
||||
[0xa2bfe8a1, 0x4cf10364], [0xa81a664b, 0xbc423001],
|
||||
[0xc24b8b70, 0xd0f89791], [0xc76c51a3, 0x0654be30],
|
||||
[0xd192e819, 0xd6ef5218], [0xd6990624, 0x5565a910],
|
||||
[0xf40e3585, 0x5771202a], [0x106aa070, 0x32bbd1b8],
|
||||
[0x19a4c116, 0xb8d2d0c8], [0x1e376c08, 0x5141ab53],
|
||||
[0x2748774c, 0xdf8eeb99], [0x34b0bcb5, 0xe19b48a8],
|
||||
[0x391c0cb3, 0xc5c95a63], [0x4ed8aa4a, 0xe3418acb],
|
||||
[0x5b9cca4f, 0x7763e373], [0x682e6ff3, 0xd6b2b8a3],
|
||||
[0x748f82ee, 0x5defb2fc], [0x78a5636f, 0x43172f60],
|
||||
[0x84c87814, 0xa1f0ab72], [0x8cc70208, 0x1a6439ec],
|
||||
[0x90befffa, 0x23631e28], [0xa4506ceb, 0xde82bde9],
|
||||
[0xbef9a3f7, 0xb2c67915], [0xc67178f2, 0xe372532b],
|
||||
[0xca273ece, 0xea26619c], [0xd186b8c7, 0x21c0c207],
|
||||
[0xeada7dd6, 0xcde0eb1e], [0xf57d4f7f, 0xee6ed178],
|
||||
[0x06f067aa, 0x72176fba], [0x0a637dc5, 0xa2c898a6],
|
||||
[0x113f9804, 0xbef90dae], [0x1b710b35, 0x131c471b],
|
||||
[0x28db77f5, 0x23047d84], [0x32caab7b, 0x40c72493],
|
||||
[0x3c9ebe0a, 0x15c9bebc], [0x431d67c4, 0x9c100d4c],
|
||||
[0x4cc5d4be, 0xcb3e42b6], [0x597f299c, 0xfc657e2a],
|
||||
[0x5fcb6fab, 0x3ad6faec], [0x6c44198c, 0x4a475817]
|
||||
];
|
||||
|
||||
// initial hash states
|
||||
_states = {};
|
||||
_states['SHA-512'] = [
|
||||
[0x6a09e667, 0xf3bcc908],
|
||||
[0xbb67ae85, 0x84caa73b],
|
||||
[0x3c6ef372, 0xfe94f82b],
|
||||
[0xa54ff53a, 0x5f1d36f1],
|
||||
[0x510e527f, 0xade682d1],
|
||||
[0x9b05688c, 0x2b3e6c1f],
|
||||
[0x1f83d9ab, 0xfb41bd6b],
|
||||
[0x5be0cd19, 0x137e2179]
|
||||
];
|
||||
_states['SHA-384'] = [
|
||||
[0xcbbb9d5d, 0xc1059ed8],
|
||||
[0x629a292a, 0x367cd507],
|
||||
[0x9159015a, 0x3070dd17],
|
||||
[0x152fecd8, 0xf70e5939],
|
||||
[0x67332667, 0xffc00b31],
|
||||
[0x8eb44a87, 0x68581511],
|
||||
[0xdb0c2e0d, 0x64f98fa7],
|
||||
[0x47b5481d, 0xbefa4fa4]
|
||||
];
|
||||
_states['SHA-512/256'] = [
|
||||
[0x22312194, 0xFC2BF72C],
|
||||
[0x9F555FA3, 0xC84C64C2],
|
||||
[0x2393B86B, 0x6F53B151],
|
||||
[0x96387719, 0x5940EABD],
|
||||
[0x96283EE2, 0xA88EFFE3],
|
||||
[0xBE5E1E25, 0x53863992],
|
||||
[0x2B0199FC, 0x2C85B8AA],
|
||||
[0x0EB72DDC, 0x81C52CA2]
|
||||
];
|
||||
_states['SHA-512/224'] = [
|
||||
[0x8C3D37C8, 0x19544DA2],
|
||||
[0x73E19966, 0x89DCD4D6],
|
||||
[0x1DFAB7AE, 0x32FF9C82],
|
||||
[0x679DD514, 0x582F9FCF],
|
||||
[0x0F6D2B69, 0x7BD44DA8],
|
||||
[0x77E36F73, 0x04C48942],
|
||||
[0x3F9D85A8, 0x6A1D36C8],
|
||||
[0x1112E6AD, 0x91D692A1]
|
||||
];
|
||||
|
||||
// now initialized
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a SHA-512 state with the given byte buffer.
|
||||
*
|
||||
* @param s the SHA-512 state to update.
|
||||
* @param w the array to use to store words.
|
||||
* @param bytes the byte buffer to update with.
|
||||
*/
|
||||
function _update(s, w, bytes) {
|
||||
// consume 512 bit (128 byte) chunks
|
||||
var t1_hi, t1_lo;
|
||||
var t2_hi, t2_lo;
|
||||
var s0_hi, s0_lo;
|
||||
var s1_hi, s1_lo;
|
||||
var ch_hi, ch_lo;
|
||||
var maj_hi, maj_lo;
|
||||
var a_hi, a_lo;
|
||||
var b_hi, b_lo;
|
||||
var c_hi, c_lo;
|
||||
var d_hi, d_lo;
|
||||
var e_hi, e_lo;
|
||||
var f_hi, f_lo;
|
||||
var g_hi, g_lo;
|
||||
var h_hi, h_lo;
|
||||
var i, hi, lo, w2, w7, w15, w16;
|
||||
var len = bytes.length();
|
||||
while(len >= 128) {
|
||||
// the w array will be populated with sixteen 64-bit big-endian words
|
||||
// and then extended into 64 64-bit words according to SHA-512
|
||||
for(i = 0; i < 16; ++i) {
|
||||
w[i][0] = bytes.getInt32() >>> 0;
|
||||
w[i][1] = bytes.getInt32() >>> 0;
|
||||
}
|
||||
for(; i < 80; ++i) {
|
||||
// for word 2 words ago: ROTR 19(x) ^ ROTR 61(x) ^ SHR 6(x)
|
||||
w2 = w[i - 2];
|
||||
hi = w2[0];
|
||||
lo = w2[1];
|
||||
|
||||
// high bits
|
||||
t1_hi = (
|
||||
((hi >>> 19) | (lo << 13)) ^ // ROTR 19
|
||||
((lo >>> 29) | (hi << 3)) ^ // ROTR 61/(swap + ROTR 29)
|
||||
(hi >>> 6)) >>> 0; // SHR 6
|
||||
// low bits
|
||||
t1_lo = (
|
||||
((hi << 13) | (lo >>> 19)) ^ // ROTR 19
|
||||
((lo << 3) | (hi >>> 29)) ^ // ROTR 61/(swap + ROTR 29)
|
||||
((hi << 26) | (lo >>> 6))) >>> 0; // SHR 6
|
||||
|
||||
// for word 15 words ago: ROTR 1(x) ^ ROTR 8(x) ^ SHR 7(x)
|
||||
w15 = w[i - 15];
|
||||
hi = w15[0];
|
||||
lo = w15[1];
|
||||
|
||||
// high bits
|
||||
t2_hi = (
|
||||
((hi >>> 1) | (lo << 31)) ^ // ROTR 1
|
||||
((hi >>> 8) | (lo << 24)) ^ // ROTR 8
|
||||
(hi >>> 7)) >>> 0; // SHR 7
|
||||
// low bits
|
||||
t2_lo = (
|
||||
((hi << 31) | (lo >>> 1)) ^ // ROTR 1
|
||||
((hi << 24) | (lo >>> 8)) ^ // ROTR 8
|
||||
((hi << 25) | (lo >>> 7))) >>> 0; // SHR 7
|
||||
|
||||
// sum(t1, word 7 ago, t2, word 16 ago) modulo 2^64 (carry lo overflow)
|
||||
w7 = w[i - 7];
|
||||
w16 = w[i - 16];
|
||||
lo = (t1_lo + w7[1] + t2_lo + w16[1]);
|
||||
w[i][0] = (t1_hi + w7[0] + t2_hi + w16[0] +
|
||||
((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
w[i][1] = lo >>> 0;
|
||||
}
|
||||
|
||||
// initialize hash value for this chunk
|
||||
a_hi = s[0][0];
|
||||
a_lo = s[0][1];
|
||||
b_hi = s[1][0];
|
||||
b_lo = s[1][1];
|
||||
c_hi = s[2][0];
|
||||
c_lo = s[2][1];
|
||||
d_hi = s[3][0];
|
||||
d_lo = s[3][1];
|
||||
e_hi = s[4][0];
|
||||
e_lo = s[4][1];
|
||||
f_hi = s[5][0];
|
||||
f_lo = s[5][1];
|
||||
g_hi = s[6][0];
|
||||
g_lo = s[6][1];
|
||||
h_hi = s[7][0];
|
||||
h_lo = s[7][1];
|
||||
|
||||
// round function
|
||||
for(i = 0; i < 80; ++i) {
|
||||
// Sum1(e) = ROTR 14(e) ^ ROTR 18(e) ^ ROTR 41(e)
|
||||
s1_hi = (
|
||||
((e_hi >>> 14) | (e_lo << 18)) ^ // ROTR 14
|
||||
((e_hi >>> 18) | (e_lo << 14)) ^ // ROTR 18
|
||||
((e_lo >>> 9) | (e_hi << 23))) >>> 0; // ROTR 41/(swap + ROTR 9)
|
||||
s1_lo = (
|
||||
((e_hi << 18) | (e_lo >>> 14)) ^ // ROTR 14
|
||||
((e_hi << 14) | (e_lo >>> 18)) ^ // ROTR 18
|
||||
((e_lo << 23) | (e_hi >>> 9))) >>> 0; // ROTR 41/(swap + ROTR 9)
|
||||
|
||||
// Ch(e, f, g) (optimized the same way as SHA-1)
|
||||
ch_hi = (g_hi ^ (e_hi & (f_hi ^ g_hi))) >>> 0;
|
||||
ch_lo = (g_lo ^ (e_lo & (f_lo ^ g_lo))) >>> 0;
|
||||
|
||||
// Sum0(a) = ROTR 28(a) ^ ROTR 34(a) ^ ROTR 39(a)
|
||||
s0_hi = (
|
||||
((a_hi >>> 28) | (a_lo << 4)) ^ // ROTR 28
|
||||
((a_lo >>> 2) | (a_hi << 30)) ^ // ROTR 34/(swap + ROTR 2)
|
||||
((a_lo >>> 7) | (a_hi << 25))) >>> 0; // ROTR 39/(swap + ROTR 7)
|
||||
s0_lo = (
|
||||
((a_hi << 4) | (a_lo >>> 28)) ^ // ROTR 28
|
||||
((a_lo << 30) | (a_hi >>> 2)) ^ // ROTR 34/(swap + ROTR 2)
|
||||
((a_lo << 25) | (a_hi >>> 7))) >>> 0; // ROTR 39/(swap + ROTR 7)
|
||||
|
||||
// Maj(a, b, c) (optimized the same way as SHA-1)
|
||||
maj_hi = ((a_hi & b_hi) | (c_hi & (a_hi ^ b_hi))) >>> 0;
|
||||
maj_lo = ((a_lo & b_lo) | (c_lo & (a_lo ^ b_lo))) >>> 0;
|
||||
|
||||
// main algorithm
|
||||
// t1 = (h + s1 + ch + _k[i] + _w[i]) modulo 2^64 (carry lo overflow)
|
||||
lo = (h_lo + s1_lo + ch_lo + _k[i][1] + w[i][1]);
|
||||
t1_hi = (h_hi + s1_hi + ch_hi + _k[i][0] + w[i][0] +
|
||||
((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
t1_lo = lo >>> 0;
|
||||
|
||||
// t2 = s0 + maj modulo 2^64 (carry lo overflow)
|
||||
lo = s0_lo + maj_lo;
|
||||
t2_hi = (s0_hi + maj_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
t2_lo = lo >>> 0;
|
||||
|
||||
h_hi = g_hi;
|
||||
h_lo = g_lo;
|
||||
|
||||
g_hi = f_hi;
|
||||
g_lo = f_lo;
|
||||
|
||||
f_hi = e_hi;
|
||||
f_lo = e_lo;
|
||||
|
||||
// e = (d + t1) modulo 2^64 (carry lo overflow)
|
||||
lo = d_lo + t1_lo;
|
||||
e_hi = (d_hi + t1_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
e_lo = lo >>> 0;
|
||||
|
||||
d_hi = c_hi;
|
||||
d_lo = c_lo;
|
||||
|
||||
c_hi = b_hi;
|
||||
c_lo = b_lo;
|
||||
|
||||
b_hi = a_hi;
|
||||
b_lo = a_lo;
|
||||
|
||||
// a = (t1 + t2) modulo 2^64 (carry lo overflow)
|
||||
lo = t1_lo + t2_lo;
|
||||
a_hi = (t1_hi + t2_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
a_lo = lo >>> 0;
|
||||
}
|
||||
|
||||
// update hash state (additional modulo 2^64)
|
||||
lo = s[0][1] + a_lo;
|
||||
s[0][0] = (s[0][0] + a_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[0][1] = lo >>> 0;
|
||||
|
||||
lo = s[1][1] + b_lo;
|
||||
s[1][0] = (s[1][0] + b_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[1][1] = lo >>> 0;
|
||||
|
||||
lo = s[2][1] + c_lo;
|
||||
s[2][0] = (s[2][0] + c_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[2][1] = lo >>> 0;
|
||||
|
||||
lo = s[3][1] + d_lo;
|
||||
s[3][0] = (s[3][0] + d_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[3][1] = lo >>> 0;
|
||||
|
||||
lo = s[4][1] + e_lo;
|
||||
s[4][0] = (s[4][0] + e_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[4][1] = lo >>> 0;
|
||||
|
||||
lo = s[5][1] + f_lo;
|
||||
s[5][0] = (s[5][0] + f_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[5][1] = lo >>> 0;
|
||||
|
||||
lo = s[6][1] + g_lo;
|
||||
s[6][0] = (s[6][0] + g_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[6][1] = lo >>> 0;
|
||||
|
||||
lo = s[7][1] + h_lo;
|
||||
s[7][0] = (s[7][0] + h_hi + ((lo / 0x100000000) >>> 0)) >>> 0;
|
||||
s[7][1] = lo >>> 0;
|
||||
|
||||
len -= 128;
|
||||
}
|
||||
}
|
287
node_modules/node-forge/lib/socket.js
generated
vendored
Normal file
287
node_modules/node-forge/lib/socket.js
generated
vendored
Normal file
@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Socket implementation that uses flash SocketPool class as a backend.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./util');
|
||||
|
||||
// define net namespace
|
||||
var net = module.exports = forge.net = forge.net || {};
|
||||
|
||||
// map of flash ID to socket pool
|
||||
net.socketPools = {};
|
||||
|
||||
/**
|
||||
* Creates a flash socket pool.
|
||||
*
|
||||
* @param options:
|
||||
* flashId: the dom ID for the flash object element.
|
||||
* policyPort: the default policy port for sockets, 0 to use the
|
||||
* flash default.
|
||||
* policyUrl: the default policy file URL for sockets (if provided
|
||||
* used instead of a policy port).
|
||||
* msie: true if the browser is msie, false if not.
|
||||
*
|
||||
* @return the created socket pool.
|
||||
*/
|
||||
net.createSocketPool = function(options) {
|
||||
// set default
|
||||
options.msie = options.msie || false;
|
||||
|
||||
// initialize the flash interface
|
||||
var spId = options.flashId;
|
||||
var api = document.getElementById(spId);
|
||||
api.init({marshallExceptions: !options.msie});
|
||||
|
||||
// create socket pool entry
|
||||
var sp = {
|
||||
// ID of the socket pool
|
||||
id: spId,
|
||||
// flash interface
|
||||
flashApi: api,
|
||||
// map of socket ID to sockets
|
||||
sockets: {},
|
||||
// default policy port
|
||||
policyPort: options.policyPort || 0,
|
||||
// default policy URL
|
||||
policyUrl: options.policyUrl || null
|
||||
};
|
||||
net.socketPools[spId] = sp;
|
||||
|
||||
// create event handler, subscribe to flash events
|
||||
if(options.msie === true) {
|
||||
sp.handler = function(e) {
|
||||
if(e.id in sp.sockets) {
|
||||
// get handler function
|
||||
var f;
|
||||
switch(e.type) {
|
||||
case 'connect':
|
||||
f = 'connected';
|
||||
break;
|
||||
case 'close':
|
||||
f = 'closed';
|
||||
break;
|
||||
case 'socketData':
|
||||
f = 'data';
|
||||
break;
|
||||
default:
|
||||
f = 'error';
|
||||
break;
|
||||
}
|
||||
/* IE calls javascript on the thread of the external object
|
||||
that triggered the event (in this case flash) ... which will
|
||||
either run concurrently with other javascript or pre-empt any
|
||||
running javascript in the middle of its execution (BAD!) ...
|
||||
calling setTimeout() will schedule the javascript to run on
|
||||
the javascript thread and solve this EVIL problem. */
|
||||
setTimeout(function() {sp.sockets[e.id][f](e);}, 0);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
sp.handler = function(e) {
|
||||
if(e.id in sp.sockets) {
|
||||
// get handler function
|
||||
var f;
|
||||
switch(e.type) {
|
||||
case 'connect':
|
||||
f = 'connected';
|
||||
break;
|
||||
case 'close':
|
||||
f = 'closed';
|
||||
break;
|
||||
case 'socketData':
|
||||
f = 'data';
|
||||
break;
|
||||
default:
|
||||
f = 'error';
|
||||
break;
|
||||
}
|
||||
sp.sockets[e.id][f](e);
|
||||
}
|
||||
};
|
||||
}
|
||||
var handler = 'forge.net.socketPools[\'' + spId + '\'].handler';
|
||||
api.subscribe('connect', handler);
|
||||
api.subscribe('close', handler);
|
||||
api.subscribe('socketData', handler);
|
||||
api.subscribe('ioError', handler);
|
||||
api.subscribe('securityError', handler);
|
||||
|
||||
/**
|
||||
* Destroys a socket pool. The socket pool still needs to be cleaned
|
||||
* up via net.cleanup().
|
||||
*/
|
||||
sp.destroy = function() {
|
||||
delete net.socketPools[options.flashId];
|
||||
for(var id in sp.sockets) {
|
||||
sp.sockets[id].destroy();
|
||||
}
|
||||
sp.sockets = {};
|
||||
api.cleanup();
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new socket.
|
||||
*
|
||||
* @param options:
|
||||
* connected: function(event) called when the socket connects.
|
||||
* closed: function(event) called when the socket closes.
|
||||
* data: function(event) called when socket data has arrived,
|
||||
* it can be read from the socket using receive().
|
||||
* error: function(event) called when a socket error occurs.
|
||||
*/
|
||||
sp.createSocket = function(options) {
|
||||
// default to empty options
|
||||
options = options || {};
|
||||
|
||||
// create flash socket
|
||||
var id = api.create();
|
||||
|
||||
// create javascript socket wrapper
|
||||
var socket = {
|
||||
id: id,
|
||||
// set handlers
|
||||
connected: options.connected || function(e) {},
|
||||
closed: options.closed || function(e) {},
|
||||
data: options.data || function(e) {},
|
||||
error: options.error || function(e) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys this socket.
|
||||
*/
|
||||
socket.destroy = function() {
|
||||
api.destroy(id);
|
||||
delete sp.sockets[id];
|
||||
};
|
||||
|
||||
/**
|
||||
* Connects this socket.
|
||||
*
|
||||
* @param options:
|
||||
* host: the host to connect to.
|
||||
* port: the port to connect to.
|
||||
* policyPort: the policy port to use (if non-default), 0 to
|
||||
* use the flash default.
|
||||
* policyUrl: the policy file URL to use (instead of port).
|
||||
*/
|
||||
socket.connect = function(options) {
|
||||
// give precedence to policy URL over policy port
|
||||
// if no policy URL and passed port isn't 0, use default port,
|
||||
// otherwise use 0 for the port
|
||||
var policyUrl = options.policyUrl || null;
|
||||
var policyPort = 0;
|
||||
if(policyUrl === null && options.policyPort !== 0) {
|
||||
policyPort = options.policyPort || sp.policyPort;
|
||||
}
|
||||
api.connect(id, options.host, options.port, policyPort, policyUrl);
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes this socket.
|
||||
*/
|
||||
socket.close = function() {
|
||||
api.close(id);
|
||||
socket.closed({
|
||||
id: socket.id,
|
||||
type: 'close',
|
||||
bytesAvailable: 0
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the socket is connected or not.
|
||||
*
|
||||
* @return true if connected, false if not.
|
||||
*/
|
||||
socket.isConnected = function() {
|
||||
return api.isConnected(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes bytes to this socket.
|
||||
*
|
||||
* @param bytes the bytes (as a string) to write.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
socket.send = function(bytes) {
|
||||
return api.send(id, forge.util.encode64(bytes));
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads bytes from this socket (non-blocking). Fewer than the number
|
||||
* of bytes requested may be read if enough bytes are not available.
|
||||
*
|
||||
* This method should be called from the data handler if there are
|
||||
* enough bytes available. To see how many bytes are available, check
|
||||
* the 'bytesAvailable' property on the event in the data handler or
|
||||
* call the bytesAvailable() function on the socket. If the browser is
|
||||
* msie, then the bytesAvailable() function should be used to avoid
|
||||
* race conditions. Otherwise, using the property on the data handler's
|
||||
* event may be quicker.
|
||||
*
|
||||
* @param count the maximum number of bytes to read.
|
||||
*
|
||||
* @return the bytes read (as a string) or null on error.
|
||||
*/
|
||||
socket.receive = function(count) {
|
||||
var rval = api.receive(id, count).rval;
|
||||
return (rval === null) ? null : forge.util.decode64(rval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the number of bytes available for receiving on the socket.
|
||||
*
|
||||
* @return the number of bytes available for receiving.
|
||||
*/
|
||||
socket.bytesAvailable = function() {
|
||||
return api.getBytesAvailable(id);
|
||||
};
|
||||
|
||||
// store and return socket
|
||||
sp.sockets[id] = socket;
|
||||
return socket;
|
||||
};
|
||||
|
||||
return sp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys a flash socket pool.
|
||||
*
|
||||
* @param options:
|
||||
* flashId: the dom ID for the flash object element.
|
||||
*/
|
||||
net.destroySocketPool = function(options) {
|
||||
if(options.flashId in net.socketPools) {
|
||||
var sp = net.socketPools[options.flashId];
|
||||
sp.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new socket.
|
||||
*
|
||||
* @param options:
|
||||
* flashId: the dom ID for the flash object element.
|
||||
* connected: function(event) called when the socket connects.
|
||||
* closed: function(event) called when the socket closes.
|
||||
* data: function(event) called when socket data has arrived, it
|
||||
* can be read from the socket using receive().
|
||||
* error: function(event) called when a socket error occurs.
|
||||
*
|
||||
* @return the created socket.
|
||||
*/
|
||||
net.createSocket = function(options) {
|
||||
var socket = null;
|
||||
if(options.flashId in net.socketPools) {
|
||||
// get related socket pool
|
||||
var sp = net.socketPools[options.flashId];
|
||||
socket = sp.createSocket(options);
|
||||
}
|
||||
return socket;
|
||||
};
|
236
node_modules/node-forge/lib/ssh.js
generated
vendored
Normal file
236
node_modules/node-forge/lib/ssh.js
generated
vendored
Normal file
@ -0,0 +1,236 @@
|
||||
/**
|
||||
* Functions to output keys in SSH-friendly formats.
|
||||
*
|
||||
* This is part of the Forge project which may be used under the terms of
|
||||
* either the BSD License or the GNU General Public License (GPL) Version 2.
|
||||
*
|
||||
* See: https://github.com/digitalbazaar/forge/blob/cbebca3780658703d925b61b2caffb1d263a6c1d/LICENSE
|
||||
*
|
||||
* @author https://github.com/shellac
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./aes');
|
||||
require('./hmac');
|
||||
require('./md5');
|
||||
require('./sha1');
|
||||
require('./util');
|
||||
|
||||
var ssh = module.exports = forge.ssh = forge.ssh || {};
|
||||
|
||||
/**
|
||||
* Encodes (and optionally encrypts) a private RSA key as a Putty PPK file.
|
||||
*
|
||||
* @param privateKey the key.
|
||||
* @param passphrase a passphrase to protect the key (falsy for no encryption).
|
||||
* @param comment a comment to include in the key file.
|
||||
*
|
||||
* @return the PPK file as a string.
|
||||
*/
|
||||
ssh.privateKeyToPutty = function(privateKey, passphrase, comment) {
|
||||
comment = comment || '';
|
||||
passphrase = passphrase || '';
|
||||
var algorithm = 'ssh-rsa';
|
||||
var encryptionAlgorithm = (passphrase === '') ? 'none' : 'aes256-cbc';
|
||||
|
||||
var ppk = 'PuTTY-User-Key-File-2: ' + algorithm + '\r\n';
|
||||
ppk += 'Encryption: ' + encryptionAlgorithm + '\r\n';
|
||||
ppk += 'Comment: ' + comment + '\r\n';
|
||||
|
||||
// public key into buffer for ppk
|
||||
var pubbuffer = forge.util.createBuffer();
|
||||
_addStringToBuffer(pubbuffer, algorithm);
|
||||
_addBigIntegerToBuffer(pubbuffer, privateKey.e);
|
||||
_addBigIntegerToBuffer(pubbuffer, privateKey.n);
|
||||
|
||||
// write public key
|
||||
var pub = forge.util.encode64(pubbuffer.bytes(), 64);
|
||||
var length = Math.floor(pub.length / 66) + 1; // 66 = 64 + \r\n
|
||||
ppk += 'Public-Lines: ' + length + '\r\n';
|
||||
ppk += pub;
|
||||
|
||||
// private key into a buffer
|
||||
var privbuffer = forge.util.createBuffer();
|
||||
_addBigIntegerToBuffer(privbuffer, privateKey.d);
|
||||
_addBigIntegerToBuffer(privbuffer, privateKey.p);
|
||||
_addBigIntegerToBuffer(privbuffer, privateKey.q);
|
||||
_addBigIntegerToBuffer(privbuffer, privateKey.qInv);
|
||||
|
||||
// optionally encrypt the private key
|
||||
var priv;
|
||||
if(!passphrase) {
|
||||
// use the unencrypted buffer
|
||||
priv = forge.util.encode64(privbuffer.bytes(), 64);
|
||||
} else {
|
||||
// encrypt RSA key using passphrase
|
||||
var encLen = privbuffer.length() + 16 - 1;
|
||||
encLen -= encLen % 16;
|
||||
|
||||
// pad private key with sha1-d data -- needs to be a multiple of 16
|
||||
var padding = _sha1(privbuffer.bytes());
|
||||
|
||||
padding.truncate(padding.length() - encLen + privbuffer.length());
|
||||
privbuffer.putBuffer(padding);
|
||||
|
||||
var aeskey = forge.util.createBuffer();
|
||||
aeskey.putBuffer(_sha1('\x00\x00\x00\x00', passphrase));
|
||||
aeskey.putBuffer(_sha1('\x00\x00\x00\x01', passphrase));
|
||||
|
||||
// encrypt some bytes using CBC mode
|
||||
// key is 40 bytes, so truncate *by* 8 bytes
|
||||
var cipher = forge.aes.createEncryptionCipher(aeskey.truncate(8), 'CBC');
|
||||
cipher.start(forge.util.createBuffer().fillWithByte(0, 16));
|
||||
cipher.update(privbuffer.copy());
|
||||
cipher.finish();
|
||||
var encrypted = cipher.output;
|
||||
|
||||
// Note: this appears to differ from Putty -- is forge wrong, or putty?
|
||||
// due to padding we finish as an exact multiple of 16
|
||||
encrypted.truncate(16); // all padding
|
||||
|
||||
priv = forge.util.encode64(encrypted.bytes(), 64);
|
||||
}
|
||||
|
||||
// output private key
|
||||
length = Math.floor(priv.length / 66) + 1; // 64 + \r\n
|
||||
ppk += '\r\nPrivate-Lines: ' + length + '\r\n';
|
||||
ppk += priv;
|
||||
|
||||
// MAC
|
||||
var mackey = _sha1('putty-private-key-file-mac-key', passphrase);
|
||||
|
||||
var macbuffer = forge.util.createBuffer();
|
||||
_addStringToBuffer(macbuffer, algorithm);
|
||||
_addStringToBuffer(macbuffer, encryptionAlgorithm);
|
||||
_addStringToBuffer(macbuffer, comment);
|
||||
macbuffer.putInt32(pubbuffer.length());
|
||||
macbuffer.putBuffer(pubbuffer);
|
||||
macbuffer.putInt32(privbuffer.length());
|
||||
macbuffer.putBuffer(privbuffer);
|
||||
|
||||
var hmac = forge.hmac.create();
|
||||
hmac.start('sha1', mackey);
|
||||
hmac.update(macbuffer.bytes());
|
||||
|
||||
ppk += '\r\nPrivate-MAC: ' + hmac.digest().toHex() + '\r\n';
|
||||
|
||||
return ppk;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes a public RSA key as an OpenSSH file.
|
||||
*
|
||||
* @param key the key.
|
||||
* @param comment a comment.
|
||||
*
|
||||
* @return the public key in OpenSSH format.
|
||||
*/
|
||||
ssh.publicKeyToOpenSSH = function(key, comment) {
|
||||
var type = 'ssh-rsa';
|
||||
comment = comment || '';
|
||||
|
||||
var buffer = forge.util.createBuffer();
|
||||
_addStringToBuffer(buffer, type);
|
||||
_addBigIntegerToBuffer(buffer, key.e);
|
||||
_addBigIntegerToBuffer(buffer, key.n);
|
||||
|
||||
return type + ' ' + forge.util.encode64(buffer.bytes()) + ' ' + comment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes a private RSA key as an OpenSSH file.
|
||||
*
|
||||
* @param key the key.
|
||||
* @param passphrase a passphrase to protect the key (falsy for no encryption).
|
||||
*
|
||||
* @return the public key in OpenSSH format.
|
||||
*/
|
||||
ssh.privateKeyToOpenSSH = function(privateKey, passphrase) {
|
||||
if(!passphrase) {
|
||||
return forge.pki.privateKeyToPem(privateKey);
|
||||
}
|
||||
// OpenSSH private key is just a legacy format, it seems
|
||||
return forge.pki.encryptRsaPrivateKey(privateKey, passphrase,
|
||||
{legacy: true, algorithm: 'aes128'});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the SSH fingerprint for the given public key.
|
||||
*
|
||||
* @param options the options to use.
|
||||
* [md] the message digest object to use (defaults to forge.md.md5).
|
||||
* [encoding] an alternative output encoding, such as 'hex'
|
||||
* (defaults to none, outputs a byte buffer).
|
||||
* [delimiter] the delimiter to use between bytes for 'hex' encoded
|
||||
* output, eg: ':' (defaults to none).
|
||||
*
|
||||
* @return the fingerprint as a byte buffer or other encoding based on options.
|
||||
*/
|
||||
ssh.getPublicKeyFingerprint = function(key, options) {
|
||||
options = options || {};
|
||||
var md = options.md || forge.md.md5.create();
|
||||
|
||||
var type = 'ssh-rsa';
|
||||
var buffer = forge.util.createBuffer();
|
||||
_addStringToBuffer(buffer, type);
|
||||
_addBigIntegerToBuffer(buffer, key.e);
|
||||
_addBigIntegerToBuffer(buffer, key.n);
|
||||
|
||||
// hash public key bytes
|
||||
md.start();
|
||||
md.update(buffer.getBytes());
|
||||
var digest = md.digest();
|
||||
if(options.encoding === 'hex') {
|
||||
var hex = digest.toHex();
|
||||
if(options.delimiter) {
|
||||
return hex.match(/.{2}/g).join(options.delimiter);
|
||||
}
|
||||
return hex;
|
||||
} else if(options.encoding === 'binary') {
|
||||
return digest.getBytes();
|
||||
} else if(options.encoding) {
|
||||
throw new Error('Unknown encoding "' + options.encoding + '".');
|
||||
}
|
||||
return digest;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds len(val) then val to a buffer.
|
||||
*
|
||||
* @param buffer the buffer to add to.
|
||||
* @param val a big integer.
|
||||
*/
|
||||
function _addBigIntegerToBuffer(buffer, val) {
|
||||
var hexVal = val.toString(16);
|
||||
// ensure 2s complement +ve
|
||||
if(hexVal[0] >= '8') {
|
||||
hexVal = '00' + hexVal;
|
||||
}
|
||||
var bytes = forge.util.hexToBytes(hexVal);
|
||||
buffer.putInt32(bytes.length);
|
||||
buffer.putBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds len(val) then val to a buffer.
|
||||
*
|
||||
* @param buffer the buffer to add to.
|
||||
* @param val a string.
|
||||
*/
|
||||
function _addStringToBuffer(buffer, val) {
|
||||
buffer.putInt32(val.length);
|
||||
buffer.putString(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the arguments into one value using SHA-1.
|
||||
*
|
||||
* @return the sha1 hash of the provided arguments.
|
||||
*/
|
||||
function _sha1() {
|
||||
var sha = forge.md.sha1.create();
|
||||
var num = arguments.length;
|
||||
for (var i = 0; i < num; ++i) {
|
||||
sha.update(arguments[i]);
|
||||
}
|
||||
return sha.digest();
|
||||
}
|
725
node_modules/node-forge/lib/task.js
generated
vendored
Normal file
725
node_modules/node-forge/lib/task.js
generated
vendored
Normal file
@ -0,0 +1,725 @@
|
||||
/**
|
||||
* Support for concurrent task management and synchronization in web
|
||||
* applications.
|
||||
*
|
||||
* @author Dave Longley
|
||||
* @author David I. Lehn <dlehn@digitalbazaar.com>
|
||||
*
|
||||
* Copyright (c) 2009-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./debug');
|
||||
require('./log');
|
||||
require('./util');
|
||||
|
||||
// logging category
|
||||
var cat = 'forge.task';
|
||||
|
||||
// verbose level
|
||||
// 0: off, 1: a little, 2: a whole lot
|
||||
// Verbose debug logging is surrounded by a level check to avoid the
|
||||
// performance issues with even calling the logging code regardless if it
|
||||
// is actually logged. For performance reasons this should not be set to 2
|
||||
// for production use.
|
||||
// ex: if(sVL >= 2) forge.log.verbose(....)
|
||||
var sVL = 0;
|
||||
|
||||
// track tasks for debugging
|
||||
var sTasks = {};
|
||||
var sNextTaskId = 0;
|
||||
// debug access
|
||||
forge.debug.set(cat, 'tasks', sTasks);
|
||||
|
||||
// a map of task type to task queue
|
||||
var sTaskQueues = {};
|
||||
// debug access
|
||||
forge.debug.set(cat, 'queues', sTaskQueues);
|
||||
|
||||
// name for unnamed tasks
|
||||
var sNoTaskName = '?';
|
||||
|
||||
// maximum number of doNext() recursions before a context swap occurs
|
||||
// FIXME: might need to tweak this based on the browser
|
||||
var sMaxRecursions = 30;
|
||||
|
||||
// time slice for doing tasks before a context swap occurs
|
||||
// FIXME: might need to tweak this based on the browser
|
||||
var sTimeSlice = 20;
|
||||
|
||||
/**
|
||||
* Task states.
|
||||
*
|
||||
* READY: ready to start processing
|
||||
* RUNNING: task or a subtask is running
|
||||
* BLOCKED: task is waiting to acquire N permits to continue
|
||||
* SLEEPING: task is sleeping for a period of time
|
||||
* DONE: task is done
|
||||
* ERROR: task has an error
|
||||
*/
|
||||
var READY = 'ready';
|
||||
var RUNNING = 'running';
|
||||
var BLOCKED = 'blocked';
|
||||
var SLEEPING = 'sleeping';
|
||||
var DONE = 'done';
|
||||
var ERROR = 'error';
|
||||
|
||||
/**
|
||||
* Task actions. Used to control state transitions.
|
||||
*
|
||||
* STOP: stop processing
|
||||
* START: start processing tasks
|
||||
* BLOCK: block task from continuing until 1 or more permits are released
|
||||
* UNBLOCK: release one or more permits
|
||||
* SLEEP: sleep for a period of time
|
||||
* WAKEUP: wakeup early from SLEEPING state
|
||||
* CANCEL: cancel further tasks
|
||||
* FAIL: a failure occured
|
||||
*/
|
||||
var STOP = 'stop';
|
||||
var START = 'start';
|
||||
var BLOCK = 'block';
|
||||
var UNBLOCK = 'unblock';
|
||||
var SLEEP = 'sleep';
|
||||
var WAKEUP = 'wakeup';
|
||||
var CANCEL = 'cancel';
|
||||
var FAIL = 'fail';
|
||||
|
||||
/**
|
||||
* State transition table.
|
||||
*
|
||||
* nextState = sStateTable[currentState][action]
|
||||
*/
|
||||
var sStateTable = {};
|
||||
|
||||
sStateTable[READY] = {};
|
||||
sStateTable[READY][STOP] = READY;
|
||||
sStateTable[READY][START] = RUNNING;
|
||||
sStateTable[READY][CANCEL] = DONE;
|
||||
sStateTable[READY][FAIL] = ERROR;
|
||||
|
||||
sStateTable[RUNNING] = {};
|
||||
sStateTable[RUNNING][STOP] = READY;
|
||||
sStateTable[RUNNING][START] = RUNNING;
|
||||
sStateTable[RUNNING][BLOCK] = BLOCKED;
|
||||
sStateTable[RUNNING][UNBLOCK] = RUNNING;
|
||||
sStateTable[RUNNING][SLEEP] = SLEEPING;
|
||||
sStateTable[RUNNING][WAKEUP] = RUNNING;
|
||||
sStateTable[RUNNING][CANCEL] = DONE;
|
||||
sStateTable[RUNNING][FAIL] = ERROR;
|
||||
|
||||
sStateTable[BLOCKED] = {};
|
||||
sStateTable[BLOCKED][STOP] = BLOCKED;
|
||||
sStateTable[BLOCKED][START] = BLOCKED;
|
||||
sStateTable[BLOCKED][BLOCK] = BLOCKED;
|
||||
sStateTable[BLOCKED][UNBLOCK] = BLOCKED;
|
||||
sStateTable[BLOCKED][SLEEP] = BLOCKED;
|
||||
sStateTable[BLOCKED][WAKEUP] = BLOCKED;
|
||||
sStateTable[BLOCKED][CANCEL] = DONE;
|
||||
sStateTable[BLOCKED][FAIL] = ERROR;
|
||||
|
||||
sStateTable[SLEEPING] = {};
|
||||
sStateTable[SLEEPING][STOP] = SLEEPING;
|
||||
sStateTable[SLEEPING][START] = SLEEPING;
|
||||
sStateTable[SLEEPING][BLOCK] = SLEEPING;
|
||||
sStateTable[SLEEPING][UNBLOCK] = SLEEPING;
|
||||
sStateTable[SLEEPING][SLEEP] = SLEEPING;
|
||||
sStateTable[SLEEPING][WAKEUP] = SLEEPING;
|
||||
sStateTable[SLEEPING][CANCEL] = DONE;
|
||||
sStateTable[SLEEPING][FAIL] = ERROR;
|
||||
|
||||
sStateTable[DONE] = {};
|
||||
sStateTable[DONE][STOP] = DONE;
|
||||
sStateTable[DONE][START] = DONE;
|
||||
sStateTable[DONE][BLOCK] = DONE;
|
||||
sStateTable[DONE][UNBLOCK] = DONE;
|
||||
sStateTable[DONE][SLEEP] = DONE;
|
||||
sStateTable[DONE][WAKEUP] = DONE;
|
||||
sStateTable[DONE][CANCEL] = DONE;
|
||||
sStateTable[DONE][FAIL] = ERROR;
|
||||
|
||||
sStateTable[ERROR] = {};
|
||||
sStateTable[ERROR][STOP] = ERROR;
|
||||
sStateTable[ERROR][START] = ERROR;
|
||||
sStateTable[ERROR][BLOCK] = ERROR;
|
||||
sStateTable[ERROR][UNBLOCK] = ERROR;
|
||||
sStateTable[ERROR][SLEEP] = ERROR;
|
||||
sStateTable[ERROR][WAKEUP] = ERROR;
|
||||
sStateTable[ERROR][CANCEL] = ERROR;
|
||||
sStateTable[ERROR][FAIL] = ERROR;
|
||||
|
||||
/**
|
||||
* Creates a new task.
|
||||
*
|
||||
* @param options options for this task
|
||||
* run: the run function for the task (required)
|
||||
* name: the run function for the task (optional)
|
||||
* parent: parent of this task (optional)
|
||||
*
|
||||
* @return the empty task.
|
||||
*/
|
||||
var Task = function(options) {
|
||||
// task id
|
||||
this.id = -1;
|
||||
|
||||
// task name
|
||||
this.name = options.name || sNoTaskName;
|
||||
|
||||
// task has no parent
|
||||
this.parent = options.parent || null;
|
||||
|
||||
// save run function
|
||||
this.run = options.run;
|
||||
|
||||
// create a queue of subtasks to run
|
||||
this.subtasks = [];
|
||||
|
||||
// error flag
|
||||
this.error = false;
|
||||
|
||||
// state of the task
|
||||
this.state = READY;
|
||||
|
||||
// number of times the task has been blocked (also the number
|
||||
// of permits needed to be released to continue running)
|
||||
this.blocks = 0;
|
||||
|
||||
// timeout id when sleeping
|
||||
this.timeoutId = null;
|
||||
|
||||
// no swap time yet
|
||||
this.swapTime = null;
|
||||
|
||||
// no user data
|
||||
this.userData = null;
|
||||
|
||||
// initialize task
|
||||
// FIXME: deal with overflow
|
||||
this.id = sNextTaskId++;
|
||||
sTasks[this.id] = this;
|
||||
if(sVL >= 1) {
|
||||
forge.log.verbose(cat, '[%s][%s] init', this.id, this.name, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs debug information on this task and the system state.
|
||||
*/
|
||||
Task.prototype.debug = function(msg) {
|
||||
msg = msg || '';
|
||||
forge.log.debug(cat, msg,
|
||||
'[%s][%s] task:', this.id, this.name, this,
|
||||
'subtasks:', this.subtasks.length,
|
||||
'queue:', sTaskQueues);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a subtask to run after task.doNext() or task.fail() is called.
|
||||
*
|
||||
* @param name human readable name for this task (optional).
|
||||
* @param subrun a function to run that takes the current task as
|
||||
* its first parameter.
|
||||
*
|
||||
* @return the current task (useful for chaining next() calls).
|
||||
*/
|
||||
Task.prototype.next = function(name, subrun) {
|
||||
// juggle parameters if it looks like no name is given
|
||||
if(typeof(name) === 'function') {
|
||||
subrun = name;
|
||||
|
||||
// inherit parent's name
|
||||
name = this.name;
|
||||
}
|
||||
// create subtask, set parent to this task, propagate callbacks
|
||||
var subtask = new Task({
|
||||
run: subrun,
|
||||
name: name,
|
||||
parent: this
|
||||
});
|
||||
// start subtasks running
|
||||
subtask.state = RUNNING;
|
||||
subtask.type = this.type;
|
||||
subtask.successCallback = this.successCallback || null;
|
||||
subtask.failureCallback = this.failureCallback || null;
|
||||
|
||||
// queue a new subtask
|
||||
this.subtasks.push(subtask);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds subtasks to run in parallel after task.doNext() or task.fail()
|
||||
* is called.
|
||||
*
|
||||
* @param name human readable name for this task (optional).
|
||||
* @param subrun functions to run that take the current task as
|
||||
* their first parameter.
|
||||
*
|
||||
* @return the current task (useful for chaining next() calls).
|
||||
*/
|
||||
Task.prototype.parallel = function(name, subrun) {
|
||||
// juggle parameters if it looks like no name is given
|
||||
if(forge.util.isArray(name)) {
|
||||
subrun = name;
|
||||
|
||||
// inherit parent's name
|
||||
name = this.name;
|
||||
}
|
||||
// Wrap parallel tasks in a regular task so they are started at the
|
||||
// proper time.
|
||||
return this.next(name, function(task) {
|
||||
// block waiting for subtasks
|
||||
var ptask = task;
|
||||
ptask.block(subrun.length);
|
||||
|
||||
// we pass the iterator from the loop below as a parameter
|
||||
// to a function because it is otherwise included in the
|
||||
// closure and changes as the loop changes -- causing i
|
||||
// to always be set to its highest value
|
||||
var startParallelTask = function(pname, pi) {
|
||||
forge.task.start({
|
||||
type: pname,
|
||||
run: function(task) {
|
||||
subrun[pi](task);
|
||||
},
|
||||
success: function(task) {
|
||||
ptask.unblock();
|
||||
},
|
||||
failure: function(task) {
|
||||
ptask.unblock();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for(var i = 0; i < subrun.length; i++) {
|
||||
// Type must be unique so task starts in parallel:
|
||||
// name + private string + task id + sub-task index
|
||||
// start tasks in parallel and unblock when the finish
|
||||
var pname = name + '__parallel-' + task.id + '-' + i;
|
||||
var pi = i;
|
||||
startParallelTask(pname, pi);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops a running task.
|
||||
*/
|
||||
Task.prototype.stop = function() {
|
||||
this.state = sStateTable[this.state][STOP];
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts running a task.
|
||||
*/
|
||||
Task.prototype.start = function() {
|
||||
this.error = false;
|
||||
this.state = sStateTable[this.state][START];
|
||||
|
||||
// try to restart
|
||||
if(this.state === RUNNING) {
|
||||
this.start = new Date();
|
||||
this.run(this);
|
||||
runNext(this, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Blocks a task until it one or more permits have been released. The
|
||||
* task will not resume until the requested number of permits have
|
||||
* been released with call(s) to unblock().
|
||||
*
|
||||
* @param n number of permits to wait for(default: 1).
|
||||
*/
|
||||
Task.prototype.block = function(n) {
|
||||
n = typeof(n) === 'undefined' ? 1 : n;
|
||||
this.blocks += n;
|
||||
if(this.blocks > 0) {
|
||||
this.state = sStateTable[this.state][BLOCK];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Releases a permit to unblock a task. If a task was blocked by
|
||||
* requesting N permits via block(), then it will only continue
|
||||
* running once enough permits have been released via unblock() calls.
|
||||
*
|
||||
* If multiple processes need to synchronize with a single task then
|
||||
* use a condition variable (see forge.task.createCondition). It is
|
||||
* an error to unblock a task more times than it has been blocked.
|
||||
*
|
||||
* @param n number of permits to release (default: 1).
|
||||
*
|
||||
* @return the current block count (task is unblocked when count is 0)
|
||||
*/
|
||||
Task.prototype.unblock = function(n) {
|
||||
n = typeof(n) === 'undefined' ? 1 : n;
|
||||
this.blocks -= n;
|
||||
if(this.blocks === 0 && this.state !== DONE) {
|
||||
this.state = RUNNING;
|
||||
runNext(this, 0);
|
||||
}
|
||||
return this.blocks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sleep for a period of time before resuming tasks.
|
||||
*
|
||||
* @param n number of milliseconds to sleep (default: 0).
|
||||
*/
|
||||
Task.prototype.sleep = function(n) {
|
||||
n = typeof(n) === 'undefined' ? 0 : n;
|
||||
this.state = sStateTable[this.state][SLEEP];
|
||||
var self = this;
|
||||
this.timeoutId = setTimeout(function() {
|
||||
self.timeoutId = null;
|
||||
self.state = RUNNING;
|
||||
runNext(self, 0);
|
||||
}, n);
|
||||
};
|
||||
|
||||
/**
|
||||
* Waits on a condition variable until notified. The next task will
|
||||
* not be scheduled until notification. A condition variable can be
|
||||
* created with forge.task.createCondition().
|
||||
*
|
||||
* Once cond.notify() is called, the task will continue.
|
||||
*
|
||||
* @param cond the condition variable to wait on.
|
||||
*/
|
||||
Task.prototype.wait = function(cond) {
|
||||
cond.wait(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* If sleeping, wakeup and continue running tasks.
|
||||
*/
|
||||
Task.prototype.wakeup = function() {
|
||||
if(this.state === SLEEPING) {
|
||||
cancelTimeout(this.timeoutId);
|
||||
this.timeoutId = null;
|
||||
this.state = RUNNING;
|
||||
runNext(this, 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancel all remaining subtasks of this task.
|
||||
*/
|
||||
Task.prototype.cancel = function() {
|
||||
this.state = sStateTable[this.state][CANCEL];
|
||||
// remove permits needed
|
||||
this.permitsNeeded = 0;
|
||||
// cancel timeouts
|
||||
if(this.timeoutId !== null) {
|
||||
cancelTimeout(this.timeoutId);
|
||||
this.timeoutId = null;
|
||||
}
|
||||
// remove subtasks
|
||||
this.subtasks = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes this task with failure and sets error flag. The entire
|
||||
* task will be aborted unless the next task that should execute
|
||||
* is passed as a parameter. This allows levels of subtasks to be
|
||||
* skipped. For instance, to abort only this tasks's subtasks, then
|
||||
* call fail(task.parent). To abort this task's subtasks and its
|
||||
* parent's subtasks, call fail(task.parent.parent). To abort
|
||||
* all tasks and simply call the task callback, call fail() or
|
||||
* fail(null).
|
||||
*
|
||||
* The task callback (success or failure) will always, eventually, be
|
||||
* called.
|
||||
*
|
||||
* @param next the task to continue at, or null to abort entirely.
|
||||
*/
|
||||
Task.prototype.fail = function(next) {
|
||||
// set error flag
|
||||
this.error = true;
|
||||
|
||||
// finish task
|
||||
finish(this, true);
|
||||
|
||||
if(next) {
|
||||
// propagate task info
|
||||
next.error = this.error;
|
||||
next.swapTime = this.swapTime;
|
||||
next.userData = this.userData;
|
||||
|
||||
// do next task as specified
|
||||
runNext(next, 0);
|
||||
} else {
|
||||
if(this.parent !== null) {
|
||||
// finish root task (ensures it is removed from task queue)
|
||||
var parent = this.parent;
|
||||
while(parent.parent !== null) {
|
||||
// propagate task info
|
||||
parent.error = this.error;
|
||||
parent.swapTime = this.swapTime;
|
||||
parent.userData = this.userData;
|
||||
parent = parent.parent;
|
||||
}
|
||||
finish(parent, true);
|
||||
}
|
||||
|
||||
// call failure callback if one exists
|
||||
if(this.failureCallback) {
|
||||
this.failureCallback(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Asynchronously start a task.
|
||||
*
|
||||
* @param task the task to start.
|
||||
*/
|
||||
var start = function(task) {
|
||||
task.error = false;
|
||||
task.state = sStateTable[task.state][START];
|
||||
setTimeout(function() {
|
||||
if(task.state === RUNNING) {
|
||||
task.swapTime = +new Date();
|
||||
task.run(task);
|
||||
runNext(task, 0);
|
||||
}
|
||||
}, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the next subtask or finish this task.
|
||||
*
|
||||
* @param task the task to process.
|
||||
* @param recurse the recursion count.
|
||||
*/
|
||||
var runNext = function(task, recurse) {
|
||||
// get time since last context swap (ms), if enough time has passed set
|
||||
// swap to true to indicate that doNext was performed asynchronously
|
||||
// also, if recurse is too high do asynchronously
|
||||
var swap =
|
||||
(recurse > sMaxRecursions) ||
|
||||
(+new Date() - task.swapTime) > sTimeSlice;
|
||||
|
||||
var doNext = function(recurse) {
|
||||
recurse++;
|
||||
if(task.state === RUNNING) {
|
||||
if(swap) {
|
||||
// update swap time
|
||||
task.swapTime = +new Date();
|
||||
}
|
||||
|
||||
if(task.subtasks.length > 0) {
|
||||
// run next subtask
|
||||
var subtask = task.subtasks.shift();
|
||||
subtask.error = task.error;
|
||||
subtask.swapTime = task.swapTime;
|
||||
subtask.userData = task.userData;
|
||||
subtask.run(subtask);
|
||||
if(!subtask.error) {
|
||||
runNext(subtask, recurse);
|
||||
}
|
||||
} else {
|
||||
finish(task);
|
||||
|
||||
if(!task.error) {
|
||||
// chain back up and run parent
|
||||
if(task.parent !== null) {
|
||||
// propagate task info
|
||||
task.parent.error = task.error;
|
||||
task.parent.swapTime = task.swapTime;
|
||||
task.parent.userData = task.userData;
|
||||
|
||||
// no subtasks left, call run next subtask on parent
|
||||
runNext(task.parent, recurse);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(swap) {
|
||||
// we're swapping, so run asynchronously
|
||||
setTimeout(doNext, 0);
|
||||
} else {
|
||||
// not swapping, so run synchronously
|
||||
doNext(recurse);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finishes a task and looks for the next task in the queue to start.
|
||||
*
|
||||
* @param task the task to finish.
|
||||
* @param suppressCallbacks true to suppress callbacks.
|
||||
*/
|
||||
var finish = function(task, suppressCallbacks) {
|
||||
// subtask is now done
|
||||
task.state = DONE;
|
||||
|
||||
delete sTasks[task.id];
|
||||
if(sVL >= 1) {
|
||||
forge.log.verbose(cat, '[%s][%s] finish',
|
||||
task.id, task.name, task);
|
||||
}
|
||||
|
||||
// only do queue processing for root tasks
|
||||
if(task.parent === null) {
|
||||
// report error if queue is missing
|
||||
if(!(task.type in sTaskQueues)) {
|
||||
forge.log.error(cat,
|
||||
'[%s][%s] task queue missing [%s]',
|
||||
task.id, task.name, task.type);
|
||||
} else if(sTaskQueues[task.type].length === 0) {
|
||||
// report error if queue is empty
|
||||
forge.log.error(cat,
|
||||
'[%s][%s] task queue empty [%s]',
|
||||
task.id, task.name, task.type);
|
||||
} else if(sTaskQueues[task.type][0] !== task) {
|
||||
// report error if this task isn't the first in the queue
|
||||
forge.log.error(cat,
|
||||
'[%s][%s] task not first in queue [%s]',
|
||||
task.id, task.name, task.type);
|
||||
} else {
|
||||
// remove ourselves from the queue
|
||||
sTaskQueues[task.type].shift();
|
||||
// clean up queue if it is empty
|
||||
if(sTaskQueues[task.type].length === 0) {
|
||||
if(sVL >= 1) {
|
||||
forge.log.verbose(cat, '[%s][%s] delete queue [%s]',
|
||||
task.id, task.name, task.type);
|
||||
}
|
||||
/* Note: Only a task can delete a queue of its own type. This
|
||||
is used as a way to synchronize tasks. If a queue for a certain
|
||||
task type exists, then a task of that type is running.
|
||||
*/
|
||||
delete sTaskQueues[task.type];
|
||||
} else {
|
||||
// dequeue the next task and start it
|
||||
if(sVL >= 1) {
|
||||
forge.log.verbose(cat,
|
||||
'[%s][%s] queue start next [%s] remain:%s',
|
||||
task.id, task.name, task.type,
|
||||
sTaskQueues[task.type].length);
|
||||
}
|
||||
sTaskQueues[task.type][0].start();
|
||||
}
|
||||
}
|
||||
|
||||
if(!suppressCallbacks) {
|
||||
// call final callback if one exists
|
||||
if(task.error && task.failureCallback) {
|
||||
task.failureCallback(task);
|
||||
} else if(!task.error && task.successCallback) {
|
||||
task.successCallback(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Tasks API */
|
||||
module.exports = forge.task = forge.task || {};
|
||||
|
||||
/**
|
||||
* Starts a new task that will run the passed function asynchronously.
|
||||
*
|
||||
* In order to finish the task, either task.doNext() or task.fail()
|
||||
* *must* be called.
|
||||
*
|
||||
* The task must have a type (a string identifier) that can be used to
|
||||
* synchronize it with other tasks of the same type. That type can also
|
||||
* be used to cancel tasks that haven't started yet.
|
||||
*
|
||||
* To start a task, the following object must be provided as a parameter
|
||||
* (each function takes a task object as its first parameter):
|
||||
*
|
||||
* {
|
||||
* type: the type of task.
|
||||
* run: the function to run to execute the task.
|
||||
* success: a callback to call when the task succeeds (optional).
|
||||
* failure: a callback to call when the task fails (optional).
|
||||
* }
|
||||
*
|
||||
* @param options the object as described above.
|
||||
*/
|
||||
forge.task.start = function(options) {
|
||||
// create a new task
|
||||
var task = new Task({
|
||||
run: options.run,
|
||||
name: options.name || sNoTaskName
|
||||
});
|
||||
task.type = options.type;
|
||||
task.successCallback = options.success || null;
|
||||
task.failureCallback = options.failure || null;
|
||||
|
||||
// append the task onto the appropriate queue
|
||||
if(!(task.type in sTaskQueues)) {
|
||||
if(sVL >= 1) {
|
||||
forge.log.verbose(cat, '[%s][%s] create queue [%s]',
|
||||
task.id, task.name, task.type);
|
||||
}
|
||||
// create the queue with the new task
|
||||
sTaskQueues[task.type] = [task];
|
||||
start(task);
|
||||
} else {
|
||||
// push the task onto the queue, it will be run after a task
|
||||
// with the same type completes
|
||||
sTaskQueues[options.type].push(task);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels all tasks of the given type that haven't started yet.
|
||||
*
|
||||
* @param type the type of task to cancel.
|
||||
*/
|
||||
forge.task.cancel = function(type) {
|
||||
// find the task queue
|
||||
if(type in sTaskQueues) {
|
||||
// empty all but the current task from the queue
|
||||
sTaskQueues[type] = [sTaskQueues[type][0]];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a condition variable to synchronize tasks. To make a task wait
|
||||
* on the condition variable, call task.wait(condition). To notify all
|
||||
* tasks that are waiting, call condition.notify().
|
||||
*
|
||||
* @return the condition variable.
|
||||
*/
|
||||
forge.task.createCondition = function() {
|
||||
var cond = {
|
||||
// all tasks that are blocked
|
||||
tasks: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Causes the given task to block until notify is called. If the task
|
||||
* is already waiting on this condition then this is a no-op.
|
||||
*
|
||||
* @param task the task to cause to wait.
|
||||
*/
|
||||
cond.wait = function(task) {
|
||||
// only block once
|
||||
if(!(task.id in cond.tasks)) {
|
||||
task.block();
|
||||
cond.tasks[task.id] = task;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies all waiting tasks to wake up.
|
||||
*/
|
||||
cond.notify = function() {
|
||||
// since unblock() will run the next task from here, make sure to
|
||||
// clear the condition's blocked task list before unblocking
|
||||
var tmp = cond.tasks;
|
||||
cond.tasks = {};
|
||||
for(var id in tmp) {
|
||||
tmp[id].unblock();
|
||||
}
|
||||
};
|
||||
|
||||
return cond;
|
||||
};
|
4269
node_modules/node-forge/lib/tls.js
generated
vendored
Normal file
4269
node_modules/node-forge/lib/tls.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
249
node_modules/node-forge/lib/tlssocket.js
generated
vendored
Normal file
249
node_modules/node-forge/lib/tlssocket.js
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
/**
|
||||
* Socket wrapping functions for TLS.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2009-2012 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./tls');
|
||||
|
||||
/**
|
||||
* Wraps a forge.net socket with a TLS layer.
|
||||
*
|
||||
* @param options:
|
||||
* sessionId: a session ID to reuse, null for a new connection if no session
|
||||
* cache is provided or it is empty.
|
||||
* caStore: an array of certificates to trust.
|
||||
* sessionCache: a session cache to use.
|
||||
* cipherSuites: an optional array of cipher suites to use, see
|
||||
* tls.CipherSuites.
|
||||
* socket: the socket to wrap.
|
||||
* virtualHost: the virtual server name to use in a TLS SNI extension.
|
||||
* verify: a handler used to custom verify certificates in the chain.
|
||||
* getCertificate: an optional callback used to get a certificate.
|
||||
* getPrivateKey: an optional callback used to get a private key.
|
||||
* getSignature: an optional callback used to get a signature.
|
||||
* deflate: function(inBytes) if provided, will deflate TLS records using
|
||||
* the deflate algorithm if the server supports it.
|
||||
* inflate: function(inBytes) if provided, will inflate TLS records using
|
||||
* the deflate algorithm if the server supports it.
|
||||
*
|
||||
* @return the TLS-wrapped socket.
|
||||
*/
|
||||
forge.tls.wrapSocket = function(options) {
|
||||
// get raw socket
|
||||
var socket = options.socket;
|
||||
|
||||
// create TLS socket
|
||||
var tlsSocket = {
|
||||
id: socket.id,
|
||||
// set handlers
|
||||
connected: socket.connected || function(e) {},
|
||||
closed: socket.closed || function(e) {},
|
||||
data: socket.data || function(e) {},
|
||||
error: socket.error || function(e) {}
|
||||
};
|
||||
|
||||
// create TLS connection
|
||||
var c = forge.tls.createConnection({
|
||||
server: false,
|
||||
sessionId: options.sessionId || null,
|
||||
caStore: options.caStore || [],
|
||||
sessionCache: options.sessionCache || null,
|
||||
cipherSuites: options.cipherSuites || null,
|
||||
virtualHost: options.virtualHost,
|
||||
verify: options.verify,
|
||||
getCertificate: options.getCertificate,
|
||||
getPrivateKey: options.getPrivateKey,
|
||||
getSignature: options.getSignature,
|
||||
deflate: options.deflate,
|
||||
inflate: options.inflate,
|
||||
connected: function(c) {
|
||||
// first handshake complete, call handler
|
||||
if(c.handshakes === 1) {
|
||||
tlsSocket.connected({
|
||||
id: socket.id,
|
||||
type: 'connect',
|
||||
bytesAvailable: c.data.length()
|
||||
});
|
||||
}
|
||||
},
|
||||
tlsDataReady: function(c) {
|
||||
// send TLS data over socket
|
||||
return socket.send(c.tlsData.getBytes());
|
||||
},
|
||||
dataReady: function(c) {
|
||||
// indicate application data is ready
|
||||
tlsSocket.data({
|
||||
id: socket.id,
|
||||
type: 'socketData',
|
||||
bytesAvailable: c.data.length()
|
||||
});
|
||||
},
|
||||
closed: function(c) {
|
||||
// close socket
|
||||
socket.close();
|
||||
},
|
||||
error: function(c, e) {
|
||||
// send error, close socket
|
||||
tlsSocket.error({
|
||||
id: socket.id,
|
||||
type: 'tlsError',
|
||||
message: e.message,
|
||||
bytesAvailable: 0,
|
||||
error: e
|
||||
});
|
||||
socket.close();
|
||||
}
|
||||
});
|
||||
|
||||
// handle doing handshake after connecting
|
||||
socket.connected = function(e) {
|
||||
c.handshake(options.sessionId);
|
||||
};
|
||||
|
||||
// handle closing TLS connection
|
||||
socket.closed = function(e) {
|
||||
if(c.open && c.handshaking) {
|
||||
// error
|
||||
tlsSocket.error({
|
||||
id: socket.id,
|
||||
type: 'ioError',
|
||||
message: 'Connection closed during handshake.',
|
||||
bytesAvailable: 0
|
||||
});
|
||||
}
|
||||
c.close();
|
||||
|
||||
// call socket handler
|
||||
tlsSocket.closed({
|
||||
id: socket.id,
|
||||
type: 'close',
|
||||
bytesAvailable: 0
|
||||
});
|
||||
};
|
||||
|
||||
// handle error on socket
|
||||
socket.error = function(e) {
|
||||
// error
|
||||
tlsSocket.error({
|
||||
id: socket.id,
|
||||
type: e.type,
|
||||
message: e.message,
|
||||
bytesAvailable: 0
|
||||
});
|
||||
c.close();
|
||||
};
|
||||
|
||||
// handle receiving raw TLS data from socket
|
||||
var _requiredBytes = 0;
|
||||
socket.data = function(e) {
|
||||
// drop data if connection not open
|
||||
if(!c.open) {
|
||||
socket.receive(e.bytesAvailable);
|
||||
} else {
|
||||
// only receive if there are enough bytes available to
|
||||
// process a record
|
||||
if(e.bytesAvailable >= _requiredBytes) {
|
||||
var count = Math.max(e.bytesAvailable, _requiredBytes);
|
||||
var data = socket.receive(count);
|
||||
if(data !== null) {
|
||||
_requiredBytes = c.process(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys this socket.
|
||||
*/
|
||||
tlsSocket.destroy = function() {
|
||||
socket.destroy();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets this socket's TLS session cache. This should be called before
|
||||
* the socket is connected or after it is closed.
|
||||
*
|
||||
* The cache is an object mapping session IDs to internal opaque state.
|
||||
* An application might need to change the cache used by a particular
|
||||
* tlsSocket between connections if it accesses multiple TLS hosts.
|
||||
*
|
||||
* @param cache the session cache to use.
|
||||
*/
|
||||
tlsSocket.setSessionCache = function(cache) {
|
||||
c.sessionCache = tls.createSessionCache(cache);
|
||||
};
|
||||
|
||||
/**
|
||||
* Connects this socket.
|
||||
*
|
||||
* @param options:
|
||||
* host: the host to connect to.
|
||||
* port: the port to connect to.
|
||||
* policyPort: the policy port to use (if non-default), 0 to
|
||||
* use the flash default.
|
||||
* policyUrl: the policy file URL to use (instead of port).
|
||||
*/
|
||||
tlsSocket.connect = function(options) {
|
||||
socket.connect(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Closes this socket.
|
||||
*/
|
||||
tlsSocket.close = function() {
|
||||
c.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the socket is connected or not.
|
||||
*
|
||||
* @return true if connected, false if not.
|
||||
*/
|
||||
tlsSocket.isConnected = function() {
|
||||
return c.isConnected && socket.isConnected();
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes bytes to this socket.
|
||||
*
|
||||
* @param bytes the bytes (as a string) to write.
|
||||
*
|
||||
* @return true on success, false on failure.
|
||||
*/
|
||||
tlsSocket.send = function(bytes) {
|
||||
return c.prepare(bytes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reads bytes from this socket (non-blocking). Fewer than the number of
|
||||
* bytes requested may be read if enough bytes are not available.
|
||||
*
|
||||
* This method should be called from the data handler if there are enough
|
||||
* bytes available. To see how many bytes are available, check the
|
||||
* 'bytesAvailable' property on the event in the data handler or call the
|
||||
* bytesAvailable() function on the socket. If the browser is msie, then the
|
||||
* bytesAvailable() function should be used to avoid race conditions.
|
||||
* Otherwise, using the property on the data handler's event may be quicker.
|
||||
*
|
||||
* @param count the maximum number of bytes to read.
|
||||
*
|
||||
* @return the bytes read (as a string) or null on error.
|
||||
*/
|
||||
tlsSocket.receive = function(count) {
|
||||
return c.data.getBytes(count);
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the number of bytes available for receiving on the socket.
|
||||
*
|
||||
* @return the number of bytes available for receiving.
|
||||
*/
|
||||
tlsSocket.bytesAvailable = function() {
|
||||
return c.data.length();
|
||||
};
|
||||
|
||||
return tlsSocket;
|
||||
};
|
2978
node_modules/node-forge/lib/util.js
generated
vendored
Normal file
2978
node_modules/node-forge/lib/util.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3271
node_modules/node-forge/lib/x509.js
generated
vendored
Normal file
3271
node_modules/node-forge/lib/x509.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
736
node_modules/node-forge/lib/xhr.js
generated
vendored
Normal file
736
node_modules/node-forge/lib/xhr.js
generated
vendored
Normal file
@ -0,0 +1,736 @@
|
||||
/**
|
||||
* XmlHttpRequest implementation that uses TLS and flash SocketPool.
|
||||
*
|
||||
* @author Dave Longley
|
||||
*
|
||||
* Copyright (c) 2010-2013 Digital Bazaar, Inc.
|
||||
*/
|
||||
var forge = require('./forge');
|
||||
require('./socket');
|
||||
require('./http');
|
||||
|
||||
/* XHR API */
|
||||
var xhrApi = module.exports = forge.xhr = forge.xhr || {};
|
||||
|
||||
(function($) {
|
||||
|
||||
// logging category
|
||||
var cat = 'forge.xhr';
|
||||
|
||||
/*
|
||||
XMLHttpRequest interface definition from:
|
||||
http://www.w3.org/TR/XMLHttpRequest
|
||||
|
||||
interface XMLHttpRequest {
|
||||
// event handler
|
||||
attribute EventListener onreadystatechange;
|
||||
|
||||
// state
|
||||
const unsigned short UNSENT = 0;
|
||||
const unsigned short OPENED = 1;
|
||||
const unsigned short HEADERS_RECEIVED = 2;
|
||||
const unsigned short LOADING = 3;
|
||||
const unsigned short DONE = 4;
|
||||
readonly attribute unsigned short readyState;
|
||||
|
||||
// request
|
||||
void open(in DOMString method, in DOMString url);
|
||||
void open(in DOMString method, in DOMString url, in boolean async);
|
||||
void open(in DOMString method, in DOMString url,
|
||||
in boolean async, in DOMString user);
|
||||
void open(in DOMString method, in DOMString url,
|
||||
in boolean async, in DOMString user, in DOMString password);
|
||||
void setRequestHeader(in DOMString header, in DOMString value);
|
||||
void send();
|
||||
void send(in DOMString data);
|
||||
void send(in Document data);
|
||||
void abort();
|
||||
|
||||
// response
|
||||
DOMString getAllResponseHeaders();
|
||||
DOMString getResponseHeader(in DOMString header);
|
||||
readonly attribute DOMString responseText;
|
||||
readonly attribute Document responseXML;
|
||||
readonly attribute unsigned short status;
|
||||
readonly attribute DOMString statusText;
|
||||
};
|
||||
*/
|
||||
|
||||
// readyStates
|
||||
var UNSENT = 0;
|
||||
var OPENED = 1;
|
||||
var HEADERS_RECEIVED = 2;
|
||||
var LOADING = 3;
|
||||
var DONE = 4;
|
||||
|
||||
// exceptions
|
||||
var INVALID_STATE_ERR = 11;
|
||||
var SYNTAX_ERR = 12;
|
||||
var SECURITY_ERR = 18;
|
||||
var NETWORK_ERR = 19;
|
||||
var ABORT_ERR = 20;
|
||||
|
||||
// private flash socket pool vars
|
||||
var _sp = null;
|
||||
var _policyPort = 0;
|
||||
var _policyUrl = null;
|
||||
|
||||
// default client (used if no special URL provided when creating an XHR)
|
||||
var _client = null;
|
||||
|
||||
// all clients including the default, key'd by full base url
|
||||
// (multiple cross-domain http clients are permitted so there may be more
|
||||
// than one client in this map)
|
||||
// TODO: provide optional clean up API for non-default clients
|
||||
var _clients = {};
|
||||
|
||||
// the default maximum number of concurrents connections per client
|
||||
var _maxConnections = 10;
|
||||
|
||||
var net = forge.net;
|
||||
var http = forge.http;
|
||||
|
||||
/**
|
||||
* Initializes flash XHR support.
|
||||
*
|
||||
* @param options:
|
||||
* url: the default base URL to connect to if xhr URLs are relative,
|
||||
* ie: https://myserver.com.
|
||||
* flashId: the dom ID of the flash SocketPool.
|
||||
* policyPort: the port that provides the server's flash policy, 0 to use
|
||||
* the flash default.
|
||||
* policyUrl: the policy file URL to use instead of a policy port.
|
||||
* msie: true if browser is internet explorer, false if not.
|
||||
* connections: the maximum number of concurrent connections.
|
||||
* caCerts: a list of PEM-formatted certificates to trust.
|
||||
* cipherSuites: an optional array of cipher suites to use,
|
||||
* see forge.tls.CipherSuites.
|
||||
* verify: optional TLS certificate verify callback to use (see forge.tls
|
||||
* for details).
|
||||
* getCertificate: an optional callback used to get a client-side
|
||||
* certificate (see forge.tls for details).
|
||||
* getPrivateKey: an optional callback used to get a client-side private
|
||||
* key (see forge.tls for details).
|
||||
* getSignature: an optional callback used to get a client-side signature
|
||||
* (see forge.tls for details).
|
||||
* persistCookies: true to use persistent cookies via flash local storage,
|
||||
* false to only keep cookies in javascript.
|
||||
* primeTlsSockets: true to immediately connect TLS sockets on their
|
||||
* creation so that they will cache TLS sessions for reuse.
|
||||
*/
|
||||
xhrApi.init = function(options) {
|
||||
forge.log.debug(cat, 'initializing', options);
|
||||
|
||||
// update default policy port and max connections
|
||||
_policyPort = options.policyPort || _policyPort;
|
||||
_policyUrl = options.policyUrl || _policyUrl;
|
||||
_maxConnections = options.connections || _maxConnections;
|
||||
|
||||
// create the flash socket pool
|
||||
_sp = net.createSocketPool({
|
||||
flashId: options.flashId,
|
||||
policyPort: _policyPort,
|
||||
policyUrl: _policyUrl,
|
||||
msie: options.msie || false
|
||||
});
|
||||
|
||||
// create default http client
|
||||
_client = http.createClient({
|
||||
url: options.url || (
|
||||
window.location.protocol + '//' + window.location.host),
|
||||
socketPool: _sp,
|
||||
policyPort: _policyPort,
|
||||
policyUrl: _policyUrl,
|
||||
connections: options.connections || _maxConnections,
|
||||
caCerts: options.caCerts,
|
||||
cipherSuites: options.cipherSuites,
|
||||
persistCookies: options.persistCookies || true,
|
||||
primeTlsSockets: options.primeTlsSockets || false,
|
||||
verify: options.verify,
|
||||
getCertificate: options.getCertificate,
|
||||
getPrivateKey: options.getPrivateKey,
|
||||
getSignature: options.getSignature
|
||||
});
|
||||
_clients[_client.url.full] = _client;
|
||||
|
||||
forge.log.debug(cat, 'ready');
|
||||
};
|
||||
|
||||
/**
|
||||
* Called to clean up the clients and socket pool.
|
||||
*/
|
||||
xhrApi.cleanup = function() {
|
||||
// destroy all clients
|
||||
for(var key in _clients) {
|
||||
_clients[key].destroy();
|
||||
}
|
||||
_clients = {};
|
||||
_client = null;
|
||||
|
||||
// destroy socket pool
|
||||
_sp.destroy();
|
||||
_sp = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a cookie.
|
||||
*
|
||||
* @param cookie the cookie with parameters:
|
||||
* name: the name of the cookie.
|
||||
* value: the value of the cookie.
|
||||
* comment: an optional comment string.
|
||||
* maxAge: the age of the cookie in seconds relative to created time.
|
||||
* secure: true if the cookie must be sent over a secure protocol.
|
||||
* httpOnly: true to restrict access to the cookie from javascript
|
||||
* (inaffective since the cookies are stored in javascript).
|
||||
* path: the path for the cookie.
|
||||
* domain: optional domain the cookie belongs to (must start with dot).
|
||||
* version: optional version of the cookie.
|
||||
* created: creation time, in UTC seconds, of the cookie.
|
||||
*/
|
||||
xhrApi.setCookie = function(cookie) {
|
||||
// default cookie expiration to never
|
||||
cookie.maxAge = cookie.maxAge || -1;
|
||||
|
||||
// if the cookie's domain is set, use the appropriate client
|
||||
if(cookie.domain) {
|
||||
// add the cookies to the applicable domains
|
||||
for(var key in _clients) {
|
||||
var client = _clients[key];
|
||||
if(http.withinCookieDomain(client.url, cookie) &&
|
||||
client.secure === cookie.secure) {
|
||||
client.setCookie(cookie);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// use the default domain
|
||||
// FIXME: should a null domain cookie be added to all clients? should
|
||||
// this be an option?
|
||||
_client.setCookie(cookie);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a cookie.
|
||||
*
|
||||
* @param name the name of the cookie.
|
||||
* @param path an optional path for the cookie (if there are multiple cookies
|
||||
* with the same name but different paths).
|
||||
* @param domain an optional domain for the cookie (if not using the default
|
||||
* domain).
|
||||
*
|
||||
* @return the cookie, cookies (if multiple matches), or null if not found.
|
||||
*/
|
||||
xhrApi.getCookie = function(name, path, domain) {
|
||||
var rval = null;
|
||||
|
||||
if(domain) {
|
||||
// get the cookies from the applicable domains
|
||||
for(var key in _clients) {
|
||||
var client = _clients[key];
|
||||
if(http.withinCookieDomain(client.url, domain)) {
|
||||
var cookie = client.getCookie(name, path);
|
||||
if(cookie !== null) {
|
||||
if(rval === null) {
|
||||
rval = cookie;
|
||||
} else if(!forge.util.isArray(rval)) {
|
||||
rval = [rval, cookie];
|
||||
} else {
|
||||
rval.push(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// get cookie from default domain
|
||||
rval = _client.getCookie(name, path);
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a cookie.
|
||||
*
|
||||
* @param name the name of the cookie.
|
||||
* @param path an optional path for the cookie (if there are multiple cookies
|
||||
* with the same name but different paths).
|
||||
* @param domain an optional domain for the cookie (if not using the default
|
||||
* domain).
|
||||
*
|
||||
* @return true if a cookie was removed, false if not.
|
||||
*/
|
||||
xhrApi.removeCookie = function(name, path, domain) {
|
||||
var rval = false;
|
||||
|
||||
if(domain) {
|
||||
// remove the cookies from the applicable domains
|
||||
for(var key in _clients) {
|
||||
var client = _clients[key];
|
||||
if(http.withinCookieDomain(client.url, domain)) {
|
||||
if(client.removeCookie(name, path)) {
|
||||
rval = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// remove cookie from default domain
|
||||
rval = _client.removeCookie(name, path);
|
||||
}
|
||||
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new XmlHttpRequest. By default the base URL, flash policy port,
|
||||
* etc, will be used. However, an XHR can be created to point at another
|
||||
* cross-domain URL.
|
||||
*
|
||||
* @param options:
|
||||
* logWarningOnError: If true and an HTTP error status code is received then
|
||||
* log a warning, otherwise log a verbose message.
|
||||
* verbose: If true be very verbose in the output including the response
|
||||
* event and response body, otherwise only include status, timing, and
|
||||
* data size.
|
||||
* logError: a multi-var log function for warnings that takes the log
|
||||
* category as the first var.
|
||||
* logWarning: a multi-var log function for warnings that takes the log
|
||||
* category as the first var.
|
||||
* logDebug: a multi-var log function for warnings that takes the log
|
||||
* category as the first var.
|
||||
* logVerbose: a multi-var log function for warnings that takes the log
|
||||
* category as the first var.
|
||||
* url: the default base URL to connect to if xhr URLs are relative,
|
||||
* eg: https://myserver.com, and note that the following options will be
|
||||
* ignored if the URL is absent or the same as the default base URL.
|
||||
* policyPort: the port that provides the server's flash policy, 0 to use
|
||||
* the flash default.
|
||||
* policyUrl: the policy file URL to use instead of a policy port.
|
||||
* connections: the maximum number of concurrent connections.
|
||||
* caCerts: a list of PEM-formatted certificates to trust.
|
||||
* cipherSuites: an optional array of cipher suites to use, see
|
||||
* forge.tls.CipherSuites.
|
||||
* verify: optional TLS certificate verify callback to use (see forge.tls
|
||||
* for details).
|
||||
* getCertificate: an optional callback used to get a client-side
|
||||
* certificate.
|
||||
* getPrivateKey: an optional callback used to get a client-side private key.
|
||||
* getSignature: an optional callback used to get a client-side signature.
|
||||
* persistCookies: true to use persistent cookies via flash local storage,
|
||||
* false to only keep cookies in javascript.
|
||||
* primeTlsSockets: true to immediately connect TLS sockets on their
|
||||
* creation so that they will cache TLS sessions for reuse.
|
||||
*
|
||||
* @return the XmlHttpRequest.
|
||||
*/
|
||||
xhrApi.create = function(options) {
|
||||
// set option defaults
|
||||
options = $.extend({
|
||||
logWarningOnError: true,
|
||||
verbose: false,
|
||||
logError: function() {},
|
||||
logWarning: function() {},
|
||||
logDebug: function() {},
|
||||
logVerbose: function() {},
|
||||
url: null
|
||||
}, options || {});
|
||||
|
||||
// private xhr state
|
||||
var _state = {
|
||||
// the http client to use
|
||||
client: null,
|
||||
// request storage
|
||||
request: null,
|
||||
// response storage
|
||||
response: null,
|
||||
// asynchronous, true if doing asynchronous communication
|
||||
asynchronous: true,
|
||||
// sendFlag, true if send has been called
|
||||
sendFlag: false,
|
||||
// errorFlag, true if a network error occurred
|
||||
errorFlag: false
|
||||
};
|
||||
|
||||
// private log functions
|
||||
var _log = {
|
||||
error: options.logError || forge.log.error,
|
||||
warning: options.logWarning || forge.log.warning,
|
||||
debug: options.logDebug || forge.log.debug,
|
||||
verbose: options.logVerbose || forge.log.verbose
|
||||
};
|
||||
|
||||
// create public xhr interface
|
||||
var xhr = {
|
||||
// an EventListener
|
||||
onreadystatechange: null,
|
||||
// readonly, the current readyState
|
||||
readyState: UNSENT,
|
||||
// a string with the response entity-body
|
||||
responseText: '',
|
||||
// a Document for response entity-bodies that are XML
|
||||
responseXML: null,
|
||||
// readonly, returns the HTTP status code (i.e. 404)
|
||||
status: 0,
|
||||
// readonly, returns the HTTP status message (i.e. 'Not Found')
|
||||
statusText: ''
|
||||
};
|
||||
|
||||
// determine which http client to use
|
||||
if(options.url === null) {
|
||||
// use default
|
||||
_state.client = _client;
|
||||
} else {
|
||||
var url = http.parseUrl(options.url);
|
||||
if(!url) {
|
||||
var error = new Error('Invalid url.');
|
||||
error.details = {
|
||||
url: options.url
|
||||
};
|
||||
}
|
||||
|
||||
// find client
|
||||
if(url.full in _clients) {
|
||||
// client found
|
||||
_state.client = _clients[url.full];
|
||||
} else {
|
||||
// create client
|
||||
_state.client = http.createClient({
|
||||
url: options.url,
|
||||
socketPool: _sp,
|
||||
policyPort: options.policyPort || _policyPort,
|
||||
policyUrl: options.policyUrl || _policyUrl,
|
||||
connections: options.connections || _maxConnections,
|
||||
caCerts: options.caCerts,
|
||||
cipherSuites: options.cipherSuites,
|
||||
persistCookies: options.persistCookies || true,
|
||||
primeTlsSockets: options.primeTlsSockets || false,
|
||||
verify: options.verify,
|
||||
getCertificate: options.getCertificate,
|
||||
getPrivateKey: options.getPrivateKey,
|
||||
getSignature: options.getSignature
|
||||
});
|
||||
_clients[url.full] = _state.client;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the request. This method will create the HTTP request to send.
|
||||
*
|
||||
* @param method the HTTP method (i.e. 'GET').
|
||||
* @param url the relative url (the HTTP request path).
|
||||
* @param async always true, ignored.
|
||||
* @param user always null, ignored.
|
||||
* @param password always null, ignored.
|
||||
*/
|
||||
xhr.open = function(method, url, async, user, password) {
|
||||
// 1. validate Document if one is associated
|
||||
// TODO: not implemented (not used yet)
|
||||
|
||||
// 2. validate method token
|
||||
// 3. change method to uppercase if it matches a known
|
||||
// method (here we just require it to be uppercase, and
|
||||
// we do not allow the standard methods)
|
||||
// 4. disallow CONNECT, TRACE, or TRACK with a security error
|
||||
switch(method) {
|
||||
case 'DELETE':
|
||||
case 'GET':
|
||||
case 'HEAD':
|
||||
case 'OPTIONS':
|
||||
case 'PATCH':
|
||||
case 'POST':
|
||||
case 'PUT':
|
||||
// valid method
|
||||
break;
|
||||
case 'CONNECT':
|
||||
case 'TRACE':
|
||||
case 'TRACK':
|
||||
throw new Error('CONNECT, TRACE and TRACK methods are disallowed');
|
||||
default:
|
||||
throw new Error('Invalid method: ' + method);
|
||||
}
|
||||
|
||||
// TODO: other validation steps in algorithm are not implemented
|
||||
|
||||
// 19. set send flag to false
|
||||
// set response body to null
|
||||
// empty list of request headers
|
||||
// set request method to given method
|
||||
// set request URL
|
||||
// set username, password
|
||||
// set asychronous flag
|
||||
_state.sendFlag = false;
|
||||
xhr.responseText = '';
|
||||
xhr.responseXML = null;
|
||||
|
||||
// custom: reset status and statusText
|
||||
xhr.status = 0;
|
||||
xhr.statusText = '';
|
||||
|
||||
// create the HTTP request
|
||||
_state.request = http.createRequest({
|
||||
method: method,
|
||||
path: url
|
||||
});
|
||||
|
||||
// 20. set state to OPENED
|
||||
xhr.readyState = OPENED;
|
||||
|
||||
// 21. dispatch onreadystatechange
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds an HTTP header field to the request.
|
||||
*
|
||||
* @param header the name of the header field.
|
||||
* @param value the value of the header field.
|
||||
*/
|
||||
xhr.setRequestHeader = function(header, value) {
|
||||
// 1. if state is not OPENED or send flag is true, raise exception
|
||||
if(xhr.readyState != OPENED || _state.sendFlag) {
|
||||
throw new Error('XHR not open or sending');
|
||||
}
|
||||
|
||||
// TODO: other validation steps in spec aren't implemented
|
||||
|
||||
// set header
|
||||
_state.request.setField(header, value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends the request and any associated data.
|
||||
*
|
||||
* @param data a string or Document object to send, null to send no data.
|
||||
*/
|
||||
xhr.send = function(data) {
|
||||
// 1. if state is not OPENED or 2. send flag is true, raise
|
||||
// an invalid state exception
|
||||
if(xhr.readyState != OPENED || _state.sendFlag) {
|
||||
throw new Error('XHR not open or sending');
|
||||
}
|
||||
|
||||
// 3. ignore data if method is GET or HEAD
|
||||
if(data &&
|
||||
_state.request.method !== 'GET' &&
|
||||
_state.request.method !== 'HEAD') {
|
||||
// handle non-IE case
|
||||
if(typeof(XMLSerializer) !== 'undefined') {
|
||||
if(data instanceof Document) {
|
||||
var xs = new XMLSerializer();
|
||||
_state.request.body = xs.serializeToString(data);
|
||||
} else {
|
||||
_state.request.body = data;
|
||||
}
|
||||
} else {
|
||||
// poorly implemented IE case
|
||||
if(typeof(data.xml) !== 'undefined') {
|
||||
_state.request.body = data.xml;
|
||||
} else {
|
||||
_state.request.body = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. release storage mutex (not used)
|
||||
|
||||
// 5. set error flag to false
|
||||
_state.errorFlag = false;
|
||||
|
||||
// 6. if asynchronous is true (must be in this implementation)
|
||||
|
||||
// 6.1 set send flag to true
|
||||
_state.sendFlag = true;
|
||||
|
||||
// 6.2 dispatch onreadystatechange
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
|
||||
// create send options
|
||||
var options = {};
|
||||
options.request = _state.request;
|
||||
options.headerReady = function(e) {
|
||||
// make cookies available for ease of use/iteration
|
||||
xhr.cookies = _state.client.cookies;
|
||||
|
||||
// TODO: update document.cookie with any cookies where the
|
||||
// script's domain matches
|
||||
|
||||
// headers received
|
||||
xhr.readyState = HEADERS_RECEIVED;
|
||||
xhr.status = e.response.code;
|
||||
xhr.statusText = e.response.message;
|
||||
_state.response = e.response;
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
if(!_state.response.aborted) {
|
||||
// now loading body
|
||||
xhr.readyState = LOADING;
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
}
|
||||
};
|
||||
options.bodyReady = function(e) {
|
||||
xhr.readyState = DONE;
|
||||
var ct = e.response.getField('Content-Type');
|
||||
// Note: this null/undefined check is done outside because IE
|
||||
// dies otherwise on a "'null' is null" error
|
||||
if(ct) {
|
||||
if(ct.indexOf('text/xml') === 0 ||
|
||||
ct.indexOf('application/xml') === 0 ||
|
||||
ct.indexOf('+xml') !== -1) {
|
||||
try {
|
||||
var doc = new ActiveXObject('MicrosoftXMLDOM');
|
||||
doc.async = false;
|
||||
doc.loadXML(e.response.body);
|
||||
xhr.responseXML = doc;
|
||||
} catch(ex) {
|
||||
var parser = new DOMParser();
|
||||
xhr.responseXML = parser.parseFromString(ex.body, 'text/xml');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var length = 0;
|
||||
if(e.response.body !== null) {
|
||||
xhr.responseText = e.response.body;
|
||||
length = e.response.body.length;
|
||||
}
|
||||
// build logging output
|
||||
var req = _state.request;
|
||||
var output =
|
||||
req.method + ' ' + req.path + ' ' +
|
||||
xhr.status + ' ' + xhr.statusText + ' ' +
|
||||
length + 'B ' +
|
||||
(e.request.connectTime + e.request.time + e.response.time) +
|
||||
'ms';
|
||||
var lFunc;
|
||||
if(options.verbose) {
|
||||
lFunc = (xhr.status >= 400 && options.logWarningOnError) ?
|
||||
_log.warning : _log.verbose;
|
||||
lFunc(cat, output,
|
||||
e, e.response.body ? '\n' + e.response.body : '\nNo content');
|
||||
} else {
|
||||
lFunc = (xhr.status >= 400 && options.logWarningOnError) ?
|
||||
_log.warning : _log.debug;
|
||||
lFunc(cat, output);
|
||||
}
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
};
|
||||
options.error = function(e) {
|
||||
var req = _state.request;
|
||||
_log.error(cat, req.method + ' ' + req.path, e);
|
||||
|
||||
// 1. set response body to null
|
||||
xhr.responseText = '';
|
||||
xhr.responseXML = null;
|
||||
|
||||
// 2. set error flag to true (and reset status)
|
||||
_state.errorFlag = true;
|
||||
xhr.status = 0;
|
||||
xhr.statusText = '';
|
||||
|
||||
// 3. set state to done
|
||||
xhr.readyState = DONE;
|
||||
|
||||
// 4. asyc flag is always true, so dispatch onreadystatechange
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
};
|
||||
|
||||
// 7. send request
|
||||
_state.client.send(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Aborts the request.
|
||||
*/
|
||||
xhr.abort = function() {
|
||||
// 1. abort send
|
||||
// 2. stop network activity
|
||||
_state.request.abort();
|
||||
|
||||
// 3. set response to null
|
||||
xhr.responseText = '';
|
||||
xhr.responseXML = null;
|
||||
|
||||
// 4. set error flag to true (and reset status)
|
||||
_state.errorFlag = true;
|
||||
xhr.status = 0;
|
||||
xhr.statusText = '';
|
||||
|
||||
// 5. clear user headers
|
||||
_state.request = null;
|
||||
_state.response = null;
|
||||
|
||||
// 6. if state is DONE or UNSENT, or if OPENED and send flag is false
|
||||
if(xhr.readyState === DONE || xhr.readyState === UNSENT ||
|
||||
(xhr.readyState === OPENED && !_state.sendFlag)) {
|
||||
// 7. set ready state to unsent
|
||||
xhr.readyState = UNSENT;
|
||||
} else {
|
||||
// 6.1 set state to DONE
|
||||
xhr.readyState = DONE;
|
||||
|
||||
// 6.2 set send flag to false
|
||||
_state.sendFlag = false;
|
||||
|
||||
// 6.3 dispatch onreadystatechange
|
||||
if(xhr.onreadystatechange) {
|
||||
xhr.onreadystatechange();
|
||||
}
|
||||
|
||||
// 7. set state to UNSENT
|
||||
xhr.readyState = UNSENT;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets all response headers as a string.
|
||||
*
|
||||
* @return the HTTP-encoded response header fields.
|
||||
*/
|
||||
xhr.getAllResponseHeaders = function() {
|
||||
var rval = '';
|
||||
if(_state.response !== null) {
|
||||
var fields = _state.response.fields;
|
||||
$.each(fields, function(name, array) {
|
||||
$.each(array, function(i, value) {
|
||||
rval += name + ': ' + value + '\r\n';
|
||||
});
|
||||
});
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a single header field value or, if there are multiple
|
||||
* fields with the same name, a comma-separated list of header
|
||||
* values.
|
||||
*
|
||||
* @return the header field value(s) or null.
|
||||
*/
|
||||
xhr.getResponseHeader = function(header) {
|
||||
var rval = null;
|
||||
if(_state.response !== null) {
|
||||
if(header in _state.response.fields) {
|
||||
rval = _state.response.fields[header];
|
||||
if(forge.util.isArray(rval)) {
|
||||
rval = rval.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
};
|
||||
|
||||
return xhr;
|
||||
};
|
||||
|
||||
})(jQuery);
|
163
node_modules/node-forge/package.json
generated
vendored
Normal file
163
node_modules/node-forge/package.json
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"node-forge@0.7.4",
|
||||
"C:\\Users\\matia\\Musix"
|
||||
]
|
||||
],
|
||||
"_from": "node-forge@0.7.4",
|
||||
"_id": "node-forge@0.7.4",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-8Df0906+tq/omxuCZD6PqhPaQDYuyJ1d+VITgxoIA8zvQd1ru+nMJcDChHH324MWitIgbVkAkQoGEEVJNpn/PA==",
|
||||
"_location": "/node-forge",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "node-forge@0.7.4",
|
||||
"name": "node-forge",
|
||||
"escapedName": "node-forge",
|
||||
"rawSpec": "0.7.4",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "0.7.4"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/firebase-admin"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.4.tgz",
|
||||
"_spec": "0.7.4",
|
||||
"_where": "C:\\Users\\matia\\Musix",
|
||||
"author": {
|
||||
"name": "Digital Bazaar, Inc.",
|
||||
"email": "support@digitalbazaar.com",
|
||||
"url": "http://digitalbazaar.com/"
|
||||
},
|
||||
"browser": {
|
||||
"buffer": false,
|
||||
"crypto": false,
|
||||
"process": false
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/digitalbazaar/forge/issues",
|
||||
"email": "support@digitalbazaar.com"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Dave Longley",
|
||||
"email": "dlongley@digitalbazaar.com"
|
||||
},
|
||||
{
|
||||
"name": "David I. Lehn",
|
||||
"email": "dlehn@digitalbazaar.com"
|
||||
},
|
||||
{
|
||||
"name": "Stefan Siegl",
|
||||
"email": "stesie@brokenpipe.de"
|
||||
},
|
||||
{
|
||||
"name": "Christoph Dorn",
|
||||
"email": "christoph@christophdorn.com"
|
||||
}
|
||||
],
|
||||
"description": "JavaScript implementations of network transports, cryptography, ciphers, PKI, message digests, and various utilities.",
|
||||
"devDependencies": {
|
||||
"browserify": "^16.1.0",
|
||||
"commander": "^2.14.1",
|
||||
"cross-env": "^5.1.3",
|
||||
"express": "^4.16.2",
|
||||
"jscs": "^3.0.7",
|
||||
"jshint": "^2.9.5",
|
||||
"karma": "^2.0.0",
|
||||
"karma-browserify": "^5.2.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-edge-launcher": "^0.4.2",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-ie-launcher": "^1.0.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-phantomjs-launcher": "^1.0.2",
|
||||
"karma-safari-launcher": "^1.0.0",
|
||||
"karma-sauce-launcher": "^1.2.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-tap-reporter": "0.0.6",
|
||||
"karma-webpack": "^2.0.13",
|
||||
"mocha": "^5.0.1",
|
||||
"mocha-lcov-reporter": "^1.2.0",
|
||||
"nodejs-websocket": "^1.7.1",
|
||||
"nyc": "^11.5.0",
|
||||
"opts": "^1.2.2",
|
||||
"webpack": "^3.11.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"files": [
|
||||
"lib/*.js",
|
||||
"flash/swf/*.swf",
|
||||
"dist/*.min.js",
|
||||
"dist/*.min.js.map"
|
||||
],
|
||||
"homepage": "https://github.com/digitalbazaar/forge",
|
||||
"jspm": {
|
||||
"format": "amd"
|
||||
},
|
||||
"keywords": [
|
||||
"aes",
|
||||
"asn",
|
||||
"asn.1",
|
||||
"cbc",
|
||||
"crypto",
|
||||
"cryptography",
|
||||
"csr",
|
||||
"des",
|
||||
"gcm",
|
||||
"hmac",
|
||||
"http",
|
||||
"https",
|
||||
"md5",
|
||||
"network",
|
||||
"pkcs",
|
||||
"pki",
|
||||
"prng",
|
||||
"rc2",
|
||||
"rsa",
|
||||
"sha1",
|
||||
"sha256",
|
||||
"sha384",
|
||||
"sha512",
|
||||
"ssh",
|
||||
"tls",
|
||||
"x.509",
|
||||
"x509"
|
||||
],
|
||||
"license": "(BSD-3-Clause OR GPL-2.0)",
|
||||
"main": "lib/index.js",
|
||||
"name": "node-forge",
|
||||
"nyc": {
|
||||
"exclude": [
|
||||
"tests"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/digitalbazaar/forge.git"
|
||||
},
|
||||
"scripts": {
|
||||
"_jscs": "jscs *.js lib/*.js tests/*.js tests/unit/*.js tests/legacy/*.js tests/issues/*.js tests/websockets/*.js",
|
||||
"_jshint": "jshint *.js lib/*.js tests/*.js tests/unit/*.js tests/legacy/*.js tests/issues/*.js tests/websockets/*.js",
|
||||
"build": "webpack",
|
||||
"coverage": "rm -rf coverage && nyc --reporter=lcov --reporter=text-summary npm test",
|
||||
"coverage-report": "nyc report",
|
||||
"jscs": "jscs *.js lib/*.js tests/*.js tests/unit/*.js tests/legacy/*.js tests/issues/*.js tests/websockets/*.js",
|
||||
"jshint": "jshint *.js lib/*.js tests/unit/*.js tests/legacy/*.js tests/issues/*.js tests/websockets/*.js",
|
||||
"prepublish": "npm run build",
|
||||
"test": "cross-env NODE_ENV=test mocha -t 30000 -R ${REPORTER:-spec} tests/unit/index.js",
|
||||
"test-build": "webpack --config webpack-tests.config.js",
|
||||
"test-karma": "karma start",
|
||||
"test-karma-sauce": "karma start karma-sauce.conf",
|
||||
"test-server": "node tests/server.js",
|
||||
"test-server-webid": "node tests/websockets/server-webid.js",
|
||||
"test-server-ws": "node tests/websockets/server-ws.js"
|
||||
},
|
||||
"version": "0.7.4"
|
||||
}
|
Reference in New Issue
Block a user