mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-06-27 06:29:24 +00:00
Add dependencies/vendor (whatsapp)
This commit is contained in:
674
vendor/go.mau.fi/libsignal/LICENSE
vendored
Normal file
674
vendor/go.mau.fi/libsignal/LICENSE
vendored
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. 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
|
||||
them 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 prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. 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.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
libsignal-protocol-go
|
||||
Copyright (C) 2017 RadicalApp LLC
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
libsignal-protocol-go Copyright (C) 2017 RadicalApp LLC
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
101
vendor/go.mau.fi/libsignal/cipher/Cbc.go
vendored
Normal file
101
vendor/go.mau.fi/libsignal/cipher/Cbc.go
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
CBC describes a block cipher mode. In cryptography, a block cipher mode of operation is an algorithm that uses a
|
||||
block cipher to provide an information service such as confidentiality or authenticity. A block cipher by itself
|
||||
is only suitable for the secure cryptographic transformation (encryption or decryption) of one fixed-length group of
|
||||
bits called a block. A mode of operation describes how to repeatedly apply a cipher's single-block operation to
|
||||
securely transform amounts of data larger than a block.
|
||||
|
||||
This package simplifies the usage of AES-256-CBC.
|
||||
*/
|
||||
package cipher
|
||||
|
||||
/*
|
||||
Some code is provided by the GitHub user locked (github.com/locked):
|
||||
https://gist.github.com/locked/b066aa1ddeb2b28e855e
|
||||
Thanks!
|
||||
*/
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
/*
|
||||
Decrypt is a function that decrypts a given cipher text with a provided key and initialization vector(iv).
|
||||
*/
|
||||
func DecryptCbc(iv, key, ciphertext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(ciphertext) < aes.BlockSize {
|
||||
return nil, fmt.Errorf("ciphertext is shorter then block size: %d / %d", len(ciphertext), aes.BlockSize)
|
||||
}
|
||||
|
||||
if iv == nil {
|
||||
iv = ciphertext[:aes.BlockSize]
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
}
|
||||
|
||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
||||
|
||||
return unpad(ciphertext)
|
||||
}
|
||||
|
||||
/*
|
||||
Encrypt is a function that encrypts plaintext with a given key and an optional initialization vector(iv).
|
||||
*/
|
||||
func EncryptCbc(iv, key, plaintext []byte) ([]byte, error) {
|
||||
plaintext = pad(plaintext, aes.BlockSize)
|
||||
|
||||
if len(plaintext)%aes.BlockSize != 0 {
|
||||
return nil, fmt.Errorf("plaintext is not a multiple of the block size: %d / %d", len(plaintext), aes.BlockSize)
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ciphertext []byte
|
||||
if iv == nil {
|
||||
ciphertext = make([]byte, aes.BlockSize+len(plaintext))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||
cbc.CryptBlocks(ciphertext[aes.BlockSize:], plaintext)
|
||||
} else {
|
||||
ciphertext = make([]byte, len(plaintext))
|
||||
|
||||
cbc := cipher.NewCBCEncrypter(block, iv)
|
||||
cbc.CryptBlocks(ciphertext, plaintext)
|
||||
}
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func pad(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
func unpad(src []byte) ([]byte, error) {
|
||||
length := len(src)
|
||||
padLen := int(src[length-1])
|
||||
|
||||
if padLen > length {
|
||||
return nil, fmt.Errorf("padding is greater then the length: %d / %d", padLen, length)
|
||||
}
|
||||
|
||||
return src[:(length - padLen)], nil
|
||||
}
|
105
vendor/go.mau.fi/libsignal/cipher/Cipher.go
vendored
Normal file
105
vendor/go.mau.fi/libsignal/cipher/Cipher.go
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
// Package cipher is a package for common encrypt/decrypt of symmetric key messages.
|
||||
package cipher
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// Decrypt will use the given key, iv, and ciphertext and return
|
||||
// the plaintext bytes.
|
||||
func Decrypt(iv, key, ciphertext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ciphertext) < aes.BlockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
cbc := cipher.NewCBCDecrypter(block, iv)
|
||||
cbc.CryptBlocks(ciphertext, ciphertext)
|
||||
|
||||
unpaddedText, err := pkcs7Unpad(ciphertext, aes.BlockSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return unpaddedText, nil
|
||||
}
|
||||
|
||||
// Encrypt will use the given iv, key, and plaintext bytes
|
||||
// and return ciphertext bytes.
|
||||
func Encrypt(iv, key, plaintext []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paddedText, err := pkcs7Pad(plaintext, block.BlockSize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ciphertext := make([]byte, len(paddedText))
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(ciphertext, paddedText)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// PKCS7 padding.
|
||||
|
||||
// PKCS7 errors.
|
||||
var (
|
||||
// ErrInvalidBlockSize indicates hash blocksize <= 0.
|
||||
ErrInvalidBlockSize = errors.New("invalid blocksize")
|
||||
|
||||
// ErrInvalidPKCS7Data indicates bad input to PKCS7 pad or unpad.
|
||||
ErrInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)")
|
||||
|
||||
// ErrInvalidPKCS7Padding indicates PKCS7 unpad fails to bad input.
|
||||
ErrInvalidPKCS7Padding = errors.New("invalid padding on input")
|
||||
)
|
||||
|
||||
// pkcs7Pad right-pads the given byte slice with 1 to n bytes, where
|
||||
// n is the block size. The size of the result is x times n, where x
|
||||
// is at least 1.
|
||||
func pkcs7Pad(b []byte, blocksize int) ([]byte, error) {
|
||||
if blocksize <= 0 {
|
||||
return nil, ErrInvalidBlockSize
|
||||
}
|
||||
if b == nil || len(b) == 0 {
|
||||
return nil, ErrInvalidPKCS7Data
|
||||
}
|
||||
n := blocksize - (len(b) % blocksize)
|
||||
pb := make([]byte, len(b)+n)
|
||||
copy(pb, b)
|
||||
copy(pb[len(b):], bytes.Repeat([]byte{byte(n)}, n))
|
||||
return pb, nil
|
||||
}
|
||||
|
||||
// pkcs7Unpad validates and unpads data from the given bytes slice.
|
||||
// The returned value will be 1 to n bytes smaller depending on the
|
||||
// amount of padding, where n is the block size.
|
||||
func pkcs7Unpad(b []byte, blocksize int) ([]byte, error) {
|
||||
if blocksize <= 0 {
|
||||
return nil, ErrInvalidBlockSize
|
||||
}
|
||||
if b == nil || len(b) == 0 {
|
||||
return nil, ErrInvalidPKCS7Data
|
||||
}
|
||||
if len(b)%blocksize != 0 {
|
||||
return nil, ErrInvalidPKCS7Padding
|
||||
}
|
||||
c := b[len(b)-1]
|
||||
n := int(c)
|
||||
if n == 0 || n > len(b) {
|
||||
return nil, ErrInvalidPKCS7Padding
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
if b[len(b)-n+i] != c {
|
||||
return nil, ErrInvalidPKCS7Padding
|
||||
}
|
||||
}
|
||||
return b[:len(b)-n], nil
|
||||
}
|
109
vendor/go.mau.fi/libsignal/ecc/Curve.go
vendored
Normal file
109
vendor/go.mau.fi/libsignal/ecc/Curve.go
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
package ecc
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
|
||||
"go.mau.fi/libsignal/logger"
|
||||
)
|
||||
|
||||
// DjbType is the Diffie-Hellman curve type (curve25519) created by D. J. Bernstein.
|
||||
const DjbType = 0x05
|
||||
|
||||
var ErrBadKeyType = errors.New("bad key type")
|
||||
|
||||
// DecodePoint will take the given bytes and offset and return an ECPublicKeyable object.
|
||||
// This is used to check the byte at the given offset in the byte array for a special
|
||||
// "type" byte that will determine the key type. Currently only DJB EC keys are supported.
|
||||
func DecodePoint(bytes []byte, offset int) (ECPublicKeyable, error) {
|
||||
keyType := bytes[offset] & 0xFF
|
||||
|
||||
switch keyType {
|
||||
case DjbType:
|
||||
keyBytes := [32]byte{}
|
||||
copy(keyBytes[:], bytes[offset+1:])
|
||||
return NewDjbECPublicKey(keyBytes), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%w %d", ErrBadKeyType, keyType)
|
||||
}
|
||||
}
|
||||
|
||||
func CreateKeyPair(privateKey []byte) *ECKeyPair {
|
||||
var private, public [32]byte
|
||||
copy(private[:], privateKey)
|
||||
|
||||
private[0] &= 248
|
||||
private[31] &= 127
|
||||
private[31] |= 64
|
||||
|
||||
curve25519.ScalarBaseMult(&public, &private)
|
||||
|
||||
// Put data into our keypair struct
|
||||
djbECPub := NewDjbECPublicKey(public)
|
||||
djbECPriv := NewDjbECPrivateKey(private)
|
||||
keypair := NewECKeyPair(djbECPub, djbECPriv)
|
||||
|
||||
logger.Debug("Returning keypair: ", keypair)
|
||||
return keypair
|
||||
}
|
||||
|
||||
// GenerateKeyPair returns an EC Key Pair.
|
||||
func GenerateKeyPair() (*ECKeyPair, error) {
|
||||
// logger.Debug("Generating EC Key Pair...")
|
||||
// Get cryptographically secure random numbers.
|
||||
random := rand.Reader
|
||||
|
||||
// Create a byte array for our public and private keys.
|
||||
var private, public [32]byte
|
||||
|
||||
// Generate some random data
|
||||
_, err := io.ReadFull(random, private[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Documented at: http://cr.yp.to/ecdh.html
|
||||
private[0] &= 248
|
||||
private[31] &= 127
|
||||
private[31] |= 64
|
||||
|
||||
curve25519.ScalarBaseMult(&public, &private)
|
||||
|
||||
// Put data into our keypair struct
|
||||
djbECPub := NewDjbECPublicKey(public)
|
||||
djbECPriv := NewDjbECPrivateKey(private)
|
||||
keypair := NewECKeyPair(djbECPub, djbECPriv)
|
||||
|
||||
// logger.Debug("Returning keypair: ", keypair)
|
||||
|
||||
return keypair, nil
|
||||
}
|
||||
|
||||
// VerifySignature verifies that the message was signed with the given key.
|
||||
func VerifySignature(signingKey ECPublicKeyable, message []byte, signature [64]byte) bool {
|
||||
logger.Debug("Verifying signature of bytes: ", message)
|
||||
publicKey := signingKey.PublicKey()
|
||||
valid := verify(publicKey, message, &signature)
|
||||
logger.Debug("Signature valid: ", valid)
|
||||
return valid
|
||||
}
|
||||
|
||||
// CalculateSignature signs a message with the given private key.
|
||||
func CalculateSignature(signingKey ECPrivateKeyable, message []byte) [64]byte {
|
||||
logger.Debug("Signing bytes with signing key")
|
||||
// Get cryptographically secure random numbers.
|
||||
var random [64]byte
|
||||
r := rand.Reader
|
||||
io.ReadFull(r, random[:])
|
||||
|
||||
// Get the private key.
|
||||
privateKey := signingKey.Serialize()
|
||||
|
||||
// Sign the message.
|
||||
signature := sign(&privateKey, message, random)
|
||||
return *signature
|
||||
}
|
29
vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go
vendored
Normal file
29
vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package ecc
|
||||
|
||||
// NewDjbECPublicKey creates a new Curve25519 public key with the given bytes.
|
||||
func NewDjbECPublicKey(publicKey [32]byte) *DjbECPublicKey {
|
||||
key := DjbECPublicKey{
|
||||
publicKey: publicKey,
|
||||
}
|
||||
return &key
|
||||
}
|
||||
|
||||
// DjbECPublicKey implements the ECPublicKey interface and uses Curve25519.
|
||||
type DjbECPublicKey struct {
|
||||
publicKey [32]byte
|
||||
}
|
||||
|
||||
// PublicKey returns the EC public key as a byte array.
|
||||
func (d *DjbECPublicKey) PublicKey() [32]byte {
|
||||
return d.publicKey
|
||||
}
|
||||
|
||||
// Serialize returns the public key prepended by the DjbType value.
|
||||
func (d *DjbECPublicKey) Serialize() []byte {
|
||||
return append([]byte{DjbType}, d.publicKey[:]...)
|
||||
}
|
||||
|
||||
// Type returns the DjbType value.
|
||||
func (d *DjbECPublicKey) Type() int {
|
||||
return DjbType
|
||||
}
|
29
vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go
vendored
Normal file
29
vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package ecc
|
||||
|
||||
// NewDjbECPrivateKey returns a new EC private key with the given bytes.
|
||||
func NewDjbECPrivateKey(key [32]byte) *DjbECPrivateKey {
|
||||
private := DjbECPrivateKey{
|
||||
privateKey: key,
|
||||
}
|
||||
return &private
|
||||
}
|
||||
|
||||
// DjbECPrivateKey implements the ECPrivateKey interface and uses Curve25519.
|
||||
type DjbECPrivateKey struct {
|
||||
privateKey [32]byte
|
||||
}
|
||||
|
||||
// PrivateKey returns the private key as a byte-array.
|
||||
func (d *DjbECPrivateKey) PrivateKey() [32]byte {
|
||||
return d.privateKey
|
||||
}
|
||||
|
||||
// Serialize returns the private key as a byte-array.
|
||||
func (d *DjbECPrivateKey) Serialize() [32]byte {
|
||||
return d.privateKey
|
||||
}
|
||||
|
||||
// Type returns the EC type value.
|
||||
func (d *DjbECPrivateKey) Type() int {
|
||||
return DjbType
|
||||
}
|
3
vendor/go.mau.fi/libsignal/ecc/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/ecc/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package ecc provides a way to generate, sign, and use Elliptic-Curve
|
||||
// X25519 Cryptography keys.
|
||||
package ecc
|
27
vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go
vendored
Normal file
27
vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package ecc
|
||||
|
||||
// NewECKeyPair returns a new elliptic curve keypair given the specified public and private keys.
|
||||
func NewECKeyPair(publicKey ECPublicKeyable, privateKey ECPrivateKeyable) *ECKeyPair {
|
||||
keypair := ECKeyPair{
|
||||
publicKey: publicKey,
|
||||
privateKey: privateKey,
|
||||
}
|
||||
|
||||
return &keypair
|
||||
}
|
||||
|
||||
// ECKeyPair is a combination of both public and private elliptic curve keys.
|
||||
type ECKeyPair struct {
|
||||
publicKey ECPublicKeyable
|
||||
privateKey ECPrivateKeyable
|
||||
}
|
||||
|
||||
// PublicKey returns the public key from the key pair.
|
||||
func (e *ECKeyPair) PublicKey() ECPublicKeyable {
|
||||
return e.publicKey
|
||||
}
|
||||
|
||||
// PrivateKey returns the private key from the key pair.
|
||||
func (e *ECKeyPair) PrivateKey() ECPrivateKeyable {
|
||||
return e.privateKey
|
||||
}
|
7
vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go
vendored
Normal file
7
vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
package ecc
|
||||
|
||||
// ECPrivateKeyable is an interface for all elliptic curve private keys.
|
||||
type ECPrivateKeyable interface {
|
||||
Serialize() [32]byte
|
||||
Type() int
|
||||
}
|
11
vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go
vendored
Normal file
11
vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package ecc
|
||||
|
||||
// KeySize is the size of EC keys (32) with the EC type byte prepended to it.
|
||||
const KeySize int = 33
|
||||
|
||||
// ECPublicKeyable is an interface for all elliptic curve public keys.
|
||||
type ECPublicKeyable interface {
|
||||
Serialize() []byte
|
||||
Type() int
|
||||
PublicKey() [32]byte
|
||||
}
|
97
vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go
vendored
Normal file
97
vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
package ecc
|
||||
|
||||
// Package curve25519sign implements a signature scheme based on Curve25519 keys.
|
||||
// See https://moderncrypto.org/mail-archive/curves/2014/000205.html for details.
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/sha512"
|
||||
|
||||
"filippo.io/edwards25519"
|
||||
"filippo.io/edwards25519/field"
|
||||
)
|
||||
|
||||
// sign signs the message with privateKey and returns a signature as a byte slice.
|
||||
func sign(privateKey *[32]byte, message []byte, random [64]byte) *[64]byte {
|
||||
|
||||
// Calculate Ed25519 public key from Curve25519 private key
|
||||
var A edwards25519.Point
|
||||
privateKeyScalar, _ := edwards25519.NewScalar().SetBytesWithClamping(privateKey[:])
|
||||
A.ScalarBaseMult(privateKeyScalar)
|
||||
publicKey := *(*[32]byte)(A.Bytes())
|
||||
|
||||
// Calculate r
|
||||
diversifier := [32]byte{
|
||||
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
|
||||
|
||||
var r [64]byte
|
||||
hash := sha512.New()
|
||||
hash.Write(diversifier[:])
|
||||
hash.Write(privateKey[:])
|
||||
hash.Write(message)
|
||||
hash.Write(random[:])
|
||||
hash.Sum(r[:0])
|
||||
|
||||
// Calculate R
|
||||
var rReduced *edwards25519.Scalar
|
||||
rReduced, _ = edwards25519.NewScalar().SetUniformBytes(r[:])
|
||||
var R edwards25519.Point
|
||||
R.ScalarBaseMult(rReduced)
|
||||
|
||||
var encodedR [32]byte
|
||||
encodedR = *(*[32]byte)(R.Bytes())
|
||||
|
||||
// Calculate S = r + SHA2-512(R || A_ed || msg) * a (mod L)
|
||||
var hramDigest [64]byte
|
||||
hash.Reset()
|
||||
hash.Write(encodedR[:])
|
||||
hash.Write(publicKey[:])
|
||||
hash.Write(message)
|
||||
hash.Sum(hramDigest[:0])
|
||||
hramDigestReduced, _ := edwards25519.NewScalar().SetUniformBytes(hramDigest[:])
|
||||
|
||||
sScalar := edwards25519.NewScalar().MultiplyAdd(hramDigestReduced, privateKeyScalar, rReduced)
|
||||
s := *(*[32]byte)(sScalar.Bytes())
|
||||
|
||||
signature := new([64]byte)
|
||||
copy(signature[:], encodedR[:])
|
||||
copy(signature[32:], s[:])
|
||||
signature[63] |= publicKey[31] & 0x80
|
||||
|
||||
return signature
|
||||
}
|
||||
|
||||
// verify checks whether the message has a valid signature.
|
||||
func verify(publicKey [32]byte, message []byte, signature *[64]byte) bool {
|
||||
|
||||
publicKey[31] &= 0x7F
|
||||
|
||||
/* Convert the Curve25519 public key into an Ed25519 public key. In
|
||||
particular, convert Curve25519's "montgomery" x-coordinate into an
|
||||
Ed25519 "edwards" y-coordinate:
|
||||
|
||||
ed_y = (mont_x - 1) / (mont_x + 1)
|
||||
|
||||
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
|
||||
|
||||
Then move the sign bit into the pubkey from the signature.
|
||||
*/
|
||||
|
||||
var edY, one, montX, montXMinusOne, montXPlusOne field.Element
|
||||
_, _ = montX.SetBytes(publicKey[:])
|
||||
_ = one.One()
|
||||
montXMinusOne.Subtract(&montX, &one)
|
||||
montXPlusOne.Add(&montX, &one)
|
||||
montXPlusOne.Invert(&montXPlusOne)
|
||||
edY.Multiply(&montXMinusOne, &montXPlusOne)
|
||||
|
||||
A_ed := *(*[32]byte)(edY.Bytes())
|
||||
|
||||
A_ed[31] |= signature[63] & 0x80
|
||||
signature[63] &= 0x7F
|
||||
|
||||
return ed25519.Verify(A_ed[:], message, signature[:])
|
||||
}
|
141
vendor/go.mau.fi/libsignal/groups/GroupCipher.go
vendored
Normal file
141
vendor/go.mau.fi/libsignal/groups/GroupCipher.go
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
package groups
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/cipher"
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/groups/ratchet"
|
||||
"go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/groups/state/store"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
)
|
||||
|
||||
// NewGroupCipher will return a new group message cipher that can be used for
|
||||
// encrypt/decrypt operations.
|
||||
func NewGroupCipher(builder *SessionBuilder, senderKeyID *protocol.SenderKeyName,
|
||||
senderKeyStore store.SenderKey) *GroupCipher {
|
||||
|
||||
return &GroupCipher{
|
||||
senderKeyID: senderKeyID,
|
||||
senderKeyStore: senderKeyStore,
|
||||
sessionBuilder: builder,
|
||||
}
|
||||
}
|
||||
|
||||
// GroupCipher is the main entry point for group encrypt/decrypt operations.
|
||||
// Once a session has been established, this can be used for
|
||||
// all encrypt/decrypt operations within that session.
|
||||
type GroupCipher struct {
|
||||
senderKeyID *protocol.SenderKeyName
|
||||
senderKeyStore store.SenderKey
|
||||
sessionBuilder *SessionBuilder
|
||||
}
|
||||
|
||||
// Encrypt will take the given message in bytes and return encrypted bytes.
|
||||
func (c *GroupCipher) Encrypt(plaintext []byte) (protocol.GroupCiphertextMessage, error) {
|
||||
// Load the sender key based on id from our store.
|
||||
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
|
||||
senderKeyState, err := keyRecord.SenderKeyState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the message key from the senderkey state.
|
||||
senderKey, err := senderKeyState.SenderChainKey().SenderMessageKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Encrypt the plaintext.
|
||||
ciphertext, err := cipher.EncryptCbc(senderKey.Iv(), senderKey.CipherKey(), plaintext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
senderKeyMessage := protocol.NewSenderKeyMessage(
|
||||
senderKeyState.KeyID(),
|
||||
senderKey.Iteration(),
|
||||
ciphertext,
|
||||
senderKeyState.SigningKey().PrivateKey(),
|
||||
c.sessionBuilder.serializer.SenderKeyMessage,
|
||||
)
|
||||
|
||||
senderKeyState.SetSenderChainKey(senderKeyState.SenderChainKey().Next())
|
||||
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
|
||||
|
||||
return senderKeyMessage, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the given message using an existing session that
|
||||
// is stored in the senderKey store.
|
||||
func (c *GroupCipher) Decrypt(senderKeyMessage *protocol.SenderKeyMessage) ([]byte, error) {
|
||||
keyRecord := c.senderKeyStore.LoadSenderKey(c.senderKeyID)
|
||||
|
||||
if keyRecord.IsEmpty() {
|
||||
return nil, fmt.Errorf("%w for %s in %s", signalerror.ErrNoSenderKeyForUser, c.senderKeyID.Sender().String(), c.senderKeyID.GroupID())
|
||||
}
|
||||
|
||||
// Get the senderkey state by id.
|
||||
senderKeyState, err := keyRecord.GetSenderKeyStateByID(senderKeyMessage.KeyID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify the signature of the senderkey message.
|
||||
verified := c.verifySignature(senderKeyState.SigningKey().PublicKey(), senderKeyMessage)
|
||||
if !verified {
|
||||
return nil, signalerror.ErrSenderKeyStateVerificationFailed
|
||||
}
|
||||
|
||||
senderKey, err := c.getSenderKey(senderKeyState, senderKeyMessage.Iteration())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decrypt the message ciphertext.
|
||||
plaintext, err := cipher.DecryptCbc(senderKey.Iv(), senderKey.CipherKey(), senderKeyMessage.Ciphertext())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Store the sender key by id.
|
||||
c.senderKeyStore.StoreSenderKey(c.senderKeyID, keyRecord)
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// verifySignature will verify the signature of the senderkey message with
|
||||
// the given public key.
|
||||
func (c *GroupCipher) verifySignature(signingPubKey ecc.ECPublicKeyable,
|
||||
senderKeyMessage *protocol.SenderKeyMessage) bool {
|
||||
|
||||
return ecc.VerifySignature(signingPubKey, senderKeyMessage.Serialize(), senderKeyMessage.Signature())
|
||||
}
|
||||
|
||||
func (c *GroupCipher) getSenderKey(senderKeyState *record.SenderKeyState, iteration uint32) (*ratchet.SenderMessageKey, error) {
|
||||
senderChainKey := senderKeyState.SenderChainKey()
|
||||
if senderChainKey.Iteration() > iteration {
|
||||
if senderKeyState.HasSenderMessageKey(iteration) {
|
||||
return senderKeyState.RemoveSenderMessageKey(iteration), nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w (current: %d, received: %d)", signalerror.ErrOldCounter, senderChainKey.Iteration(), iteration)
|
||||
}
|
||||
|
||||
if iteration-senderChainKey.Iteration() > 2000 {
|
||||
return nil, signalerror.ErrTooFarIntoFuture
|
||||
}
|
||||
|
||||
for senderChainKey.Iteration() < iteration {
|
||||
senderMessageKey, err := senderChainKey.SenderMessageKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
senderKeyState.AddSenderMessageKey(senderMessageKey)
|
||||
senderChainKey = senderChainKey.Next()
|
||||
}
|
||||
|
||||
senderKeyState.SetSenderChainKey(senderChainKey.Next())
|
||||
return senderChainKey.SenderMessageKey()
|
||||
}
|
84
vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go
vendored
Normal file
84
vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
// Package groups is responsible for setting up group SenderKey encrypted sessions.
|
||||
// Once a session has been established, GroupCipher can be used to encrypt/decrypt
|
||||
// messages in that session.
|
||||
//
|
||||
// The built sessions are unidirectional: they can be used either for sending or
|
||||
// for receiving, but not both. Sessions are constructed per (groupId + senderId +
|
||||
// deviceId) tuple. Remote logical users are identified by their senderId, and each
|
||||
// logical recipientId can have multiple physical devices.
|
||||
package groups
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/groups/state/store"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/serialize"
|
||||
"go.mau.fi/libsignal/util/keyhelper"
|
||||
)
|
||||
|
||||
// NewGroupSessionBuilder will return a new group session builder.
|
||||
func NewGroupSessionBuilder(senderKeyStore store.SenderKey,
|
||||
serializer *serialize.Serializer) *SessionBuilder {
|
||||
|
||||
return &SessionBuilder{
|
||||
senderKeyStore: senderKeyStore,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// SessionBuilder is a structure for building group sessions.
|
||||
type SessionBuilder struct {
|
||||
senderKeyStore store.SenderKey
|
||||
serializer *serialize.Serializer
|
||||
}
|
||||
|
||||
// Process will process an incoming group message and set up the corresponding
|
||||
// session for it.
|
||||
func (b *SessionBuilder) Process(senderKeyName *protocol.SenderKeyName,
|
||||
msg *protocol.SenderKeyDistributionMessage) {
|
||||
|
||||
senderKeyRecord := b.senderKeyStore.LoadSenderKey(senderKeyName)
|
||||
if senderKeyRecord == nil {
|
||||
senderKeyRecord = record.NewSenderKey(b.serializer.SenderKeyRecord, b.serializer.SenderKeyState)
|
||||
}
|
||||
senderKeyRecord.AddSenderKeyState(msg.ID(), msg.Iteration(), msg.ChainKey(), msg.SignatureKey())
|
||||
b.senderKeyStore.StoreSenderKey(senderKeyName, senderKeyRecord)
|
||||
}
|
||||
|
||||
// Create will create a new group session for the given name.
|
||||
func (b *SessionBuilder) Create(senderKeyName *protocol.SenderKeyName) (*protocol.SenderKeyDistributionMessage, error) {
|
||||
// Load the senderkey by name
|
||||
senderKeyRecord := b.senderKeyStore.LoadSenderKey(senderKeyName)
|
||||
|
||||
// If the record is empty, generate new keys.
|
||||
if senderKeyRecord == nil || senderKeyRecord.IsEmpty() {
|
||||
senderKeyRecord = record.NewSenderKey(b.serializer.SenderKeyRecord, b.serializer.SenderKeyState)
|
||||
signingKey, err := keyhelper.GenerateSenderSigningKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
senderKeyRecord.SetSenderKeyState(
|
||||
keyhelper.GenerateSenderKeyID(), 0,
|
||||
keyhelper.GenerateSenderKey(),
|
||||
signingKey,
|
||||
)
|
||||
b.senderKeyStore.StoreSenderKey(senderKeyName, senderKeyRecord)
|
||||
}
|
||||
|
||||
// Get the senderkey state.
|
||||
state, err := senderKeyRecord.SenderKeyState()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the group message to return.
|
||||
senderKeyDistributionMessage := protocol.NewSenderKeyDistributionMessage(
|
||||
state.KeyID(),
|
||||
state.SenderChainKey().Iteration(),
|
||||
state.SenderChainKey().Seed(),
|
||||
state.SigningKey().PublicKey(),
|
||||
b.serializer.SenderKeyDistributionMessage,
|
||||
)
|
||||
|
||||
return senderKeyDistributionMessage, nil
|
||||
}
|
3
vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package ratchet provides the methods necessary to establish a ratchet
|
||||
// session for group messaging.
|
||||
package ratchet
|
68
vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go
vendored
Normal file
68
vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
var messageKeySeed = []byte{0x01}
|
||||
var chainKeySeed = []byte{0x02}
|
||||
|
||||
// NewSenderChainKey will return a new SenderChainKey.
|
||||
func NewSenderChainKey(iteration uint32, chainKey []byte) *SenderChainKey {
|
||||
return &SenderChainKey{
|
||||
iteration: iteration,
|
||||
chainKey: chainKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSenderChainKeyFromStruct will return a new chain key object from the
|
||||
// given serializeable structure.
|
||||
func NewSenderChainKeyFromStruct(structure *SenderChainKeyStructure) *SenderChainKey {
|
||||
return &SenderChainKey{
|
||||
iteration: structure.Iteration,
|
||||
chainKey: structure.ChainKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewStructFromSenderChainKeys returns a serializeable structure of chain keys.
|
||||
func NewStructFromSenderChainKey(key *SenderChainKey) *SenderChainKeyStructure {
|
||||
return &SenderChainKeyStructure{
|
||||
Iteration: key.iteration,
|
||||
ChainKey: key.chainKey,
|
||||
}
|
||||
}
|
||||
|
||||
// SenderChainKeyStructure is a serializeable structure of SenderChainKeys.
|
||||
type SenderChainKeyStructure struct {
|
||||
Iteration uint32
|
||||
ChainKey []byte
|
||||
}
|
||||
|
||||
type SenderChainKey struct {
|
||||
iteration uint32
|
||||
chainKey []byte
|
||||
}
|
||||
|
||||
func (k *SenderChainKey) Iteration() uint32 {
|
||||
return k.iteration
|
||||
}
|
||||
|
||||
func (k *SenderChainKey) SenderMessageKey() (*SenderMessageKey, error) {
|
||||
return NewSenderMessageKey(k.iteration, k.getDerivative(messageKeySeed, k.chainKey))
|
||||
}
|
||||
|
||||
func (k *SenderChainKey) Next() *SenderChainKey {
|
||||
return NewSenderChainKey(k.iteration+1, k.getDerivative(chainKeySeed, k.chainKey))
|
||||
}
|
||||
|
||||
func (k *SenderChainKey) Seed() []byte {
|
||||
return k.chainKey
|
||||
}
|
||||
|
||||
func (k *SenderChainKey) getDerivative(seed []byte, key []byte) []byte {
|
||||
mac := hmac.New(sha256.New, key[:])
|
||||
mac.Write(seed)
|
||||
|
||||
return mac.Sum(nil)
|
||||
}
|
89
vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go
vendored
Normal file
89
vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// KdfInfo is optional bytes to include in deriving secrets with KDF.
|
||||
const KdfInfo string = "WhisperGroup"
|
||||
|
||||
// NewSenderMessageKey will return a new sender message key using the given
|
||||
// iteration and seed.
|
||||
func NewSenderMessageKey(iteration uint32, seed []byte) (*SenderMessageKey, error) {
|
||||
derivative, err := kdf.DeriveSecrets(seed, nil, []byte(KdfInfo), 48)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Split our derived secrets into 2 parts
|
||||
parts := bytehelper.Split(derivative, 16, 32)
|
||||
|
||||
// Build the message key.
|
||||
senderKeyMessage := &SenderMessageKey{
|
||||
iteration: iteration,
|
||||
seed: seed,
|
||||
iv: parts[0],
|
||||
cipherKey: parts[1],
|
||||
}
|
||||
|
||||
return senderKeyMessage, nil
|
||||
}
|
||||
|
||||
// NewSenderMessageKeyFromStruct will return a new message key object from the
|
||||
// given serializeable structure.
|
||||
func NewSenderMessageKeyFromStruct(structure *SenderMessageKeyStructure) *SenderMessageKey {
|
||||
return &SenderMessageKey{
|
||||
iteration: structure.Iteration,
|
||||
iv: structure.IV,
|
||||
cipherKey: structure.CipherKey,
|
||||
seed: structure.Seed,
|
||||
}
|
||||
}
|
||||
|
||||
// NewStructFromSenderMessageKey returns a serializeable structure of message keys.
|
||||
func NewStructFromSenderMessageKey(key *SenderMessageKey) *SenderMessageKeyStructure {
|
||||
return &SenderMessageKeyStructure{
|
||||
CipherKey: key.cipherKey,
|
||||
Iteration: key.iteration,
|
||||
IV: key.iv,
|
||||
Seed: key.seed,
|
||||
}
|
||||
}
|
||||
|
||||
// SenderMessageKeyStructure is a serializeable structure of SenderMessageKeys.
|
||||
type SenderMessageKeyStructure struct {
|
||||
Iteration uint32
|
||||
IV []byte
|
||||
CipherKey []byte
|
||||
Seed []byte
|
||||
}
|
||||
|
||||
// SenderMessageKey is a structure for sender message keys used in group
|
||||
// messaging.
|
||||
type SenderMessageKey struct {
|
||||
iteration uint32
|
||||
iv []byte
|
||||
cipherKey []byte
|
||||
seed []byte
|
||||
}
|
||||
|
||||
// Iteration will return the sender message key's iteration.
|
||||
func (k *SenderMessageKey) Iteration() uint32 {
|
||||
return k.iteration
|
||||
}
|
||||
|
||||
// Iv will return the sender message key's initialization vector.
|
||||
func (k *SenderMessageKey) Iv() []byte {
|
||||
return k.iv
|
||||
}
|
||||
|
||||
// CipherKey will return the key in bytes.
|
||||
func (k *SenderMessageKey) CipherKey() []byte {
|
||||
return k.cipherKey
|
||||
}
|
||||
|
||||
// Seed will return the sender message key's seed.
|
||||
func (k *SenderMessageKey) Seed() []byte {
|
||||
return k.seed
|
||||
}
|
2
vendor/go.mau.fi/libsignal/groups/state/record/Doc.go
vendored
Normal file
2
vendor/go.mau.fi/libsignal/groups/state/record/Doc.go
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
// Package record provides the state and record of a group session.
|
||||
package record
|
149
vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go
vendored
Normal file
149
vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
)
|
||||
|
||||
const maxStates = 5
|
||||
|
||||
// SenderKeySerializer is an interface for serializing and deserializing
|
||||
// SenderKey objects into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SenderKeySerializer interface {
|
||||
Serialize(preKey *SenderKeyStructure) []byte
|
||||
Deserialize(serialized []byte) (*SenderKeyStructure, error)
|
||||
}
|
||||
|
||||
// NewSenderKeyFromBytes will return a prekey record from the given bytes using the given serializer.
|
||||
func NewSenderKeyFromBytes(serialized []byte, serializer SenderKeySerializer,
|
||||
stateSerializer SenderKeyStateSerializer) (*SenderKey, error) {
|
||||
|
||||
// Use the given serializer to decode the senderkey record
|
||||
senderKeyStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSenderKeyFromStruct(senderKeyStructure, serializer, stateSerializer)
|
||||
}
|
||||
|
||||
// NewSenderKeyFromStruct returns a SenderKey record using the given serializable structure.
|
||||
func NewSenderKeyFromStruct(structure *SenderKeyStructure, serializer SenderKeySerializer,
|
||||
stateSerializer SenderKeyStateSerializer) (*SenderKey, error) {
|
||||
|
||||
// Build our sender key states from structure.
|
||||
senderKeyStates := make([]*SenderKeyState, len(structure.SenderKeyStates))
|
||||
for i := range structure.SenderKeyStates {
|
||||
var err error
|
||||
senderKeyStates[i], err = NewSenderKeyStateFromStructure(structure.SenderKeyStates[i], stateSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Build and return our session.
|
||||
senderKey := &SenderKey{
|
||||
senderKeyStates: senderKeyStates,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return senderKey, nil
|
||||
|
||||
}
|
||||
|
||||
// NewSenderKey record returns a new sender key record that can
|
||||
// be stored in a SenderKeyStore.
|
||||
func NewSenderKey(serializer SenderKeySerializer,
|
||||
stateSerializer SenderKeyStateSerializer) *SenderKey {
|
||||
|
||||
return &SenderKey{
|
||||
senderKeyStates: []*SenderKeyState{},
|
||||
serializer: serializer,
|
||||
stateSerializer: stateSerializer,
|
||||
}
|
||||
}
|
||||
|
||||
// SenderKeyStructure is a structure for serializing SenderKey records.
|
||||
type SenderKeyStructure struct {
|
||||
SenderKeyStates []*SenderKeyStateStructure
|
||||
}
|
||||
|
||||
// SenderKey record is a structure for storing pre keys inside
|
||||
// a SenderKeyStore.
|
||||
type SenderKey struct {
|
||||
senderKeyStates []*SenderKeyState
|
||||
serializer SenderKeySerializer
|
||||
stateSerializer SenderKeyStateSerializer
|
||||
}
|
||||
|
||||
// SenderKeyState will return the first sender key state in the record's
|
||||
// list of sender key states.
|
||||
func (k *SenderKey) SenderKeyState() (*SenderKeyState, error) {
|
||||
if len(k.senderKeyStates) > 0 {
|
||||
return k.senderKeyStates[0], nil
|
||||
}
|
||||
return nil, signalerror.ErrNoSenderKeyStatesInRecord
|
||||
}
|
||||
|
||||
// GetSenderKeyStateByID will return the sender key state with the given
|
||||
// key id.
|
||||
func (k *SenderKey) GetSenderKeyStateByID(keyID uint32) (*SenderKeyState, error) {
|
||||
for i := 0; i < len(k.senderKeyStates); i++ {
|
||||
if k.senderKeyStates[i].KeyID() == keyID {
|
||||
return k.senderKeyStates[i], nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("%w %d", signalerror.ErrNoSenderKeyStateForID, keyID)
|
||||
}
|
||||
|
||||
// IsEmpty will return false if there is more than one state in this
|
||||
// senderkey record.
|
||||
func (k *SenderKey) IsEmpty() bool {
|
||||
return len(k.senderKeyStates) == 0
|
||||
}
|
||||
|
||||
// AddSenderKeyState will add a new state to this senderkey record with the given
|
||||
// id, iteration, chainkey, and signature key.
|
||||
func (k *SenderKey) AddSenderKeyState(id uint32, iteration uint32,
|
||||
chainKey []byte, signatureKey ecc.ECPublicKeyable) {
|
||||
|
||||
newState := NewSenderKeyStateFromPublicKey(id, iteration, chainKey, signatureKey, k.stateSerializer)
|
||||
k.senderKeyStates = append([]*SenderKeyState{newState}, k.senderKeyStates...)
|
||||
|
||||
if len(k.senderKeyStates) > maxStates {
|
||||
k.senderKeyStates = k.senderKeyStates[:len(k.senderKeyStates)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// SetSenderKeyState will replace the current senderkey states with the given
|
||||
// senderkey state.
|
||||
func (k *SenderKey) SetSenderKeyState(id uint32, iteration uint32,
|
||||
chainKey []byte, signatureKey *ecc.ECKeyPair) {
|
||||
|
||||
newState := NewSenderKeyState(id, iteration, chainKey, signatureKey, k.stateSerializer)
|
||||
k.senderKeyStates = make([]*SenderKeyState, 0, maxStates/2)
|
||||
k.senderKeyStates = append(k.senderKeyStates, newState)
|
||||
}
|
||||
|
||||
// Serialize will return the record as serialized bytes so it can be
|
||||
// persistently stored.
|
||||
func (k *SenderKey) Serialize() []byte {
|
||||
return k.serializer.Serialize(k.Structure())
|
||||
}
|
||||
|
||||
// Structure will return a simple serializable record structure.
|
||||
// This is used for serialization to persistently
|
||||
// store a session record.
|
||||
func (k *SenderKey) Structure() *SenderKeyStructure {
|
||||
senderKeyStates := make([]*SenderKeyStateStructure, len(k.senderKeyStates))
|
||||
for i := range k.senderKeyStates {
|
||||
senderKeyStates[i] = k.senderKeyStates[i].structure()
|
||||
}
|
||||
return &SenderKeyStructure{
|
||||
SenderKeyStates: senderKeyStates,
|
||||
}
|
||||
}
|
186
vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go
vendored
Normal file
186
vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/groups/ratchet"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
const maxMessageKeys = 2000
|
||||
|
||||
// SenderKeyStateSerializer is an interface for serializing and deserializing
|
||||
// a Signal State into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SenderKeyStateSerializer interface {
|
||||
Serialize(state *SenderKeyStateStructure) []byte
|
||||
Deserialize(serialized []byte) (*SenderKeyStateStructure, error)
|
||||
}
|
||||
|
||||
// NewSenderKeyStateFromBytes will return a Signal State from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSenderKeyStateFromBytes(serialized []byte, serializer SenderKeyStateSerializer) (*SenderKeyState, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
stateStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSenderKeyStateFromStructure(stateStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSenderKeyState returns a new SenderKeyState.
|
||||
func NewSenderKeyState(keyID uint32, iteration uint32, chainKey []byte,
|
||||
signatureKey *ecc.ECKeyPair, serializer SenderKeyStateSerializer) *SenderKeyState {
|
||||
|
||||
return &SenderKeyState{
|
||||
keys: make([]*ratchet.SenderMessageKey, 0, maxMessageKeys/2),
|
||||
keyID: keyID,
|
||||
senderChainKey: ratchet.NewSenderChainKey(iteration, chainKey),
|
||||
signingKeyPair: signatureKey,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSenderKeyStateFromPublicKey returns a new SenderKeyState with the given publicKey.
|
||||
func NewSenderKeyStateFromPublicKey(keyID uint32, iteration uint32, chainKey []byte,
|
||||
signatureKey ecc.ECPublicKeyable, serializer SenderKeyStateSerializer) *SenderKeyState {
|
||||
|
||||
keyPair := ecc.NewECKeyPair(signatureKey, nil)
|
||||
|
||||
return &SenderKeyState{
|
||||
keys: make([]*ratchet.SenderMessageKey, 0, maxMessageKeys/2),
|
||||
keyID: keyID,
|
||||
senderChainKey: ratchet.NewSenderChainKey(iteration, chainKey),
|
||||
signingKeyPair: keyPair,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// NewSenderKeyStateFromStructure will return a new session state with the
|
||||
// given state structure. This structure is given back from an
|
||||
// implementation of the sender key state serializer.
|
||||
func NewSenderKeyStateFromStructure(structure *SenderKeyStateStructure,
|
||||
serializer SenderKeyStateSerializer) (*SenderKeyState, error) {
|
||||
|
||||
// Convert our ecc keys from bytes into object form.
|
||||
signingKeyPublic, err := ecc.DecodePoint(structure.SigningKeyPublic, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signingKeyPrivate := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.SigningKeyPrivate))
|
||||
|
||||
// Build our sender message keys from structure
|
||||
senderMessageKeys := make([]*ratchet.SenderMessageKey, len(structure.Keys))
|
||||
for i := range structure.Keys {
|
||||
senderMessageKeys[i] = ratchet.NewSenderMessageKeyFromStruct(structure.Keys[i])
|
||||
}
|
||||
|
||||
// Build our state object.
|
||||
state := &SenderKeyState{
|
||||
keys: senderMessageKeys,
|
||||
keyID: structure.KeyID,
|
||||
senderChainKey: ratchet.NewSenderChainKeyFromStruct(structure.SenderChainKey),
|
||||
signingKeyPair: ecc.NewECKeyPair(signingKeyPublic, signingKeyPrivate),
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// SenderKeyStateStructure is a serializeable structure of SenderKeyState.
|
||||
type SenderKeyStateStructure struct {
|
||||
Keys []*ratchet.SenderMessageKeyStructure
|
||||
KeyID uint32
|
||||
SenderChainKey *ratchet.SenderChainKeyStructure
|
||||
SigningKeyPrivate []byte
|
||||
SigningKeyPublic []byte
|
||||
}
|
||||
|
||||
// SenderKeyState is a structure for maintaining a senderkey session state.
|
||||
type SenderKeyState struct {
|
||||
keys []*ratchet.SenderMessageKey
|
||||
keyID uint32
|
||||
senderChainKey *ratchet.SenderChainKey
|
||||
signingKeyPair *ecc.ECKeyPair
|
||||
serializer SenderKeyStateSerializer
|
||||
}
|
||||
|
||||
// SigningKey returns the signing key pair of the sender key state.
|
||||
func (k *SenderKeyState) SigningKey() *ecc.ECKeyPair {
|
||||
return k.signingKeyPair
|
||||
}
|
||||
|
||||
// SenderChainKey returns the sender chain key of the state.
|
||||
func (k *SenderKeyState) SenderChainKey() *ratchet.SenderChainKey {
|
||||
return k.senderChainKey
|
||||
}
|
||||
|
||||
// KeyID returns the state's key id.
|
||||
func (k *SenderKeyState) KeyID() uint32 {
|
||||
return k.keyID
|
||||
}
|
||||
|
||||
// HasSenderMessageKey will return true if the state has a key with the
|
||||
// given iteration.
|
||||
func (k *SenderKeyState) HasSenderMessageKey(iteration uint32) bool {
|
||||
for i := 0; i < len(k.keys); i++ {
|
||||
if k.keys[i].Iteration() == iteration {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// AddSenderMessageKey will add the given sender message key to the state.
|
||||
func (k *SenderKeyState) AddSenderMessageKey(senderMsgKey *ratchet.SenderMessageKey) {
|
||||
k.keys = append(k.keys, senderMsgKey)
|
||||
|
||||
if len(k.keys) > maxMessageKeys {
|
||||
k.keys = k.keys[1:]
|
||||
}
|
||||
}
|
||||
|
||||
// SetSenderChainKey will set the state's sender chain key with the given key.
|
||||
func (k *SenderKeyState) SetSenderChainKey(senderChainKey *ratchet.SenderChainKey) {
|
||||
k.senderChainKey = senderChainKey
|
||||
}
|
||||
|
||||
// RemoveSenderMessageKey will remove the key in this state with the given iteration number.
|
||||
func (k *SenderKeyState) RemoveSenderMessageKey(iteration uint32) *ratchet.SenderMessageKey {
|
||||
for i := 0; i < len(k.keys); i++ {
|
||||
if k.keys[i].Iteration() == iteration {
|
||||
removed := k.keys[i]
|
||||
k.keys = append(k.keys[0:i], k.keys[i+1:]...)
|
||||
return removed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serialize will return the state as bytes using the given serializer.
|
||||
func (k *SenderKeyState) Serialize() []byte {
|
||||
return k.serializer.Serialize(k.structure())
|
||||
}
|
||||
|
||||
// structure will return a serializable structure of the
|
||||
// the given state so it can be persistently stored.
|
||||
func (k *SenderKeyState) structure() *SenderKeyStateStructure {
|
||||
// Convert our sender message keys into a serializeable structure
|
||||
keys := make([]*ratchet.SenderMessageKeyStructure, len(k.keys))
|
||||
for i := range k.keys {
|
||||
keys[i] = ratchet.NewStructFromSenderMessageKey(k.keys[i])
|
||||
}
|
||||
|
||||
// Build and return our state structure.
|
||||
s := &SenderKeyStateStructure{
|
||||
Keys: keys,
|
||||
KeyID: k.keyID,
|
||||
SenderChainKey: ratchet.NewStructFromSenderChainKey(k.senderChainKey),
|
||||
SigningKeyPublic: k.signingKeyPair.PublicKey().Serialize(),
|
||||
}
|
||||
if k.signingKeyPair.PrivateKey() != nil {
|
||||
s.SigningKeyPrivate = bytehelper.ArrayToSlice(k.signingKeyPair.PrivateKey().Serialize())
|
||||
}
|
||||
return s
|
||||
}
|
3
vendor/go.mau.fi/libsignal/groups/state/store/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/groups/state/store/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package store provides the storage interfaces for storing group sender
|
||||
// key records.
|
||||
package store
|
11
vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go
vendored
Normal file
11
vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
)
|
||||
|
||||
type SenderKey interface {
|
||||
StoreSenderKey(senderKeyName *protocol.SenderKeyName, keyRecord *record.SenderKey)
|
||||
LoadSenderKey(senderKeyName *protocol.SenderKeyName) *record.SenderKey
|
||||
}
|
47
vendor/go.mau.fi/libsignal/kdf/HKDF.go
vendored
Normal file
47
vendor/go.mau.fi/libsignal/kdf/HKDF.go
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
// Package kdf provides a key derivation function to calculate key output
|
||||
// and negotiate shared secrets for curve X25519 keys.
|
||||
package kdf
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/curve25519"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
|
||||
// HKDF is a hashed key derivation function type that can be used to derive keys.
|
||||
type HKDF func(inputKeyMaterial, salt, info []byte, outputLength int) ([]byte, error)
|
||||
|
||||
// DeriveSecrets derives the requested number of bytes using HKDF with the given
|
||||
// input, salt, and info.
|
||||
func DeriveSecrets(inputKeyMaterial, salt, info []byte, outputLength int) ([]byte, error) {
|
||||
kdf := hkdf.New(sha256.New, inputKeyMaterial, salt, info)
|
||||
|
||||
secrets := make([]byte, outputLength)
|
||||
length, err := io.ReadFull(kdf, secrets)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if length != outputLength {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return secrets, nil
|
||||
}
|
||||
|
||||
// CalculateSharedSecret uses DH Curve25519 to find a shared secret. The result of this function
|
||||
// should be used in `DeriveSecrets` to output the Root and Chain keys.
|
||||
func CalculateSharedSecret(theirKey, ourKey [32]byte) [32]byte {
|
||||
var sharedSecret [32]byte
|
||||
curve25519.ScalarMult(&sharedSecret, &ourKey, &theirKey)
|
||||
|
||||
return sharedSecret
|
||||
}
|
||||
|
||||
// KeyMaterial is a structure for representing a cipherkey, mac, and iv
|
||||
type KeyMaterial struct {
|
||||
CipherKey []byte
|
||||
MacKey []byte
|
||||
IV []byte
|
||||
}
|
127
vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go
vendored
Normal file
127
vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
// Package chain provides chain keys used in double ratchet sessions.
|
||||
package chain
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
)
|
||||
|
||||
var messageKeySeed = []byte{0x01}
|
||||
var chainKeySeed = []byte{0x02}
|
||||
|
||||
// NewKey returns a new chain key with the given kdf, key, and index
|
||||
func NewKey(kdf kdf.HKDF, key []byte, index uint32) *Key {
|
||||
chainKey := Key{
|
||||
kdf: kdf,
|
||||
key: key,
|
||||
index: index,
|
||||
}
|
||||
|
||||
return &chainKey
|
||||
}
|
||||
|
||||
// NewKeyFromStruct will return a chain key built from the given structure.
|
||||
func NewKeyFromStruct(structure *KeyStructure, kdf kdf.HKDF) *Key {
|
||||
return NewKey(
|
||||
kdf,
|
||||
structure.Key,
|
||||
structure.Index,
|
||||
)
|
||||
}
|
||||
|
||||
// NewStructFromKey will return a chain key structure for serialization.
|
||||
func NewStructFromKey(key *Key) *KeyStructure {
|
||||
return &KeyStructure{
|
||||
Key: key.key,
|
||||
Index: key.index,
|
||||
}
|
||||
}
|
||||
|
||||
// KeyStructure is a serializeable structure for chain keys.
|
||||
type KeyStructure struct {
|
||||
Key []byte
|
||||
Index uint32
|
||||
}
|
||||
|
||||
// Key is used for generating message keys. This key "ratchets" every time a
|
||||
// message key is generated. Every time the chain key ratchets forward, its index
|
||||
// increases by one.
|
||||
type Key struct {
|
||||
kdf kdf.HKDF
|
||||
key []byte
|
||||
index uint32 // Index's maximum size: 4,294,967,295
|
||||
}
|
||||
|
||||
// Current returns the current ChainKey struct.
|
||||
func (c *Key) Current() *Key {
|
||||
return c
|
||||
}
|
||||
|
||||
// Key returns the ChainKey's key material.
|
||||
func (c *Key) Key() []byte {
|
||||
return c.key
|
||||
}
|
||||
|
||||
// SetKey will set the ChainKey's key material.
|
||||
func (c *Key) SetKey(key []byte) {
|
||||
c.key = key
|
||||
}
|
||||
|
||||
// Index returns how many times the ChainKey has been "ratcheted" forward.
|
||||
func (c *Key) Index() uint32 {
|
||||
return c.index
|
||||
}
|
||||
|
||||
// SetIndex sets how many times the ChainKey has been "ratcheted" forward.
|
||||
func (c *Key) SetIndex(index uint32) {
|
||||
c.index = index
|
||||
}
|
||||
|
||||
// NextKey uses the key derivation function to generate a new ChainKey.
|
||||
func (c *Key) NextKey() *Key {
|
||||
nextKey := c.BaseMaterial(chainKeySeed)
|
||||
return NewKey(c.kdf, nextKey, c.index+1)
|
||||
}
|
||||
|
||||
// MessageKeys returns message keys, which includes the cipherkey, mac, iv, and index.
|
||||
func (c *Key) MessageKeys() *message.Keys {
|
||||
inputKeyMaterial := c.BaseMaterial(messageKeySeed)
|
||||
keyMaterialBytes, _ := c.kdf(inputKeyMaterial, nil, []byte(message.KdfSalt), message.DerivedSecretsSize)
|
||||
keyMaterial := newKeyMaterial(keyMaterialBytes)
|
||||
|
||||
// Use the key material returned from the key derivation function for our cipherkey, mac, and iv.
|
||||
messageKeys := message.NewKeys(
|
||||
keyMaterial.CipherKey, // Use the first 32 bytes of the key material for the CipherKey
|
||||
keyMaterial.MacKey, // Use bytes 32-64 of the key material for the MacKey
|
||||
keyMaterial.IV, // Use the last 16 bytes for the IV.
|
||||
c.Index(), // Attach the chain key's index to the message keys.
|
||||
)
|
||||
|
||||
return messageKeys
|
||||
}
|
||||
|
||||
// BaseMaterial uses hmac to derive the base material used in the key derivation function for a new key.
|
||||
func (c *Key) BaseMaterial(seed []byte) []byte {
|
||||
mac := hmac.New(sha256.New, c.key[:])
|
||||
mac.Write(seed)
|
||||
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
// NewKeyMaterial takes an 80-byte slice derived from a key derivation function and splits
|
||||
// it into the cipherkey, mac, and iv.
|
||||
func newKeyMaterial(keyMaterialBytes []byte) *kdf.KeyMaterial {
|
||||
cipherKey := keyMaterialBytes[:32] // Use the first 32 bytes of the key material for the CipherKey
|
||||
macKey := keyMaterialBytes[32:64] // Use bytes 32-64 of the key material for the MacKey
|
||||
iv := keyMaterialBytes[64:80] // Use the last 16 bytes for the IV.
|
||||
|
||||
keyMaterial := kdf.KeyMaterial{
|
||||
CipherKey: cipherKey,
|
||||
MacKey: macKey,
|
||||
IV: iv,
|
||||
}
|
||||
|
||||
return &keyMaterial
|
||||
}
|
47
vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go
vendored
Normal file
47
vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
// Package identity provides identity keys used for verifying the identity
|
||||
// of a signal user.
|
||||
package identity
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
)
|
||||
|
||||
// NewKey generates a new IdentityKey from an ECPublicKey
|
||||
func NewKey(publicKey ecc.ECPublicKeyable) *Key {
|
||||
identityKey := Key{
|
||||
publicKey: publicKey,
|
||||
}
|
||||
|
||||
return &identityKey
|
||||
}
|
||||
|
||||
// NewKeyFromBytes generates a new IdentityKey from public key bytes
|
||||
func NewKeyFromBytes(publicKey [32]byte, offset int) Key {
|
||||
identityKey := Key{
|
||||
publicKey: ecc.NewDjbECPublicKey(publicKey),
|
||||
}
|
||||
|
||||
return identityKey
|
||||
}
|
||||
|
||||
// Key is a structure for representing an identity key. This same structure can
|
||||
// be used for verifying recipient's identity key or storing our own identity key.
|
||||
type Key struct {
|
||||
publicKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// Fingerprint gets the string fingerprint representation of the public key.
|
||||
func (k *Key) Fingerprint() string {
|
||||
return hex.EncodeToString(k.publicKey.Serialize())
|
||||
}
|
||||
|
||||
// PublicKey returns the EC Public key of the identity key
|
||||
func (k *Key) PublicKey() ecc.ECPublicKeyable {
|
||||
return k.publicKey
|
||||
}
|
||||
|
||||
// Serialize returns the serialized version of the key
|
||||
func (k *Key) Serialize() []byte {
|
||||
return k.publicKey.Serialize()
|
||||
}
|
39
vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go
vendored
Normal file
39
vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
package identity
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
)
|
||||
|
||||
// NewKeyPair returns a new identity key with the given public and private keys.
|
||||
func NewKeyPair(publicKey *Key, privateKey ecc.ECPrivateKeyable) *KeyPair {
|
||||
keyPair := KeyPair{
|
||||
publicKey: publicKey,
|
||||
privateKey: privateKey,
|
||||
}
|
||||
|
||||
return &keyPair
|
||||
}
|
||||
|
||||
// NewKeyPairFromBytes returns a new identity key from the given serialized bytes.
|
||||
//func NewKeyPairFromBytes(serialized []byte) KeyPair {
|
||||
//}
|
||||
|
||||
// KeyPair is a holder for public and private identity key pair.
|
||||
type KeyPair struct {
|
||||
publicKey *Key
|
||||
privateKey ecc.ECPrivateKeyable
|
||||
}
|
||||
|
||||
// PublicKey returns the identity key's public key.
|
||||
func (k *KeyPair) PublicKey() *Key {
|
||||
return k.publicKey
|
||||
}
|
||||
|
||||
// PrivateKey returns the identity key's private key.
|
||||
func (k *KeyPair) PrivateKey() ecc.ECPrivateKeyable {
|
||||
return k.privateKey
|
||||
}
|
||||
|
||||
// Serialize returns a byte array that represents the keypair.
|
||||
//func (k *KeyPair) Serialize() []byte {
|
||||
//}
|
91
vendor/go.mau.fi/libsignal/keys/message/MessageKey.go
vendored
Normal file
91
vendor/go.mau.fi/libsignal/keys/message/MessageKey.go
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
// Package message provides a structure for message keys, which are symmetric
|
||||
// keys used for the encryption/decryption of Signal messages.
|
||||
package message
|
||||
|
||||
// DerivedSecretsSize is the size of the derived secrets for message keys.
|
||||
const DerivedSecretsSize = 80
|
||||
|
||||
// CipherKeyLength is the length of the actual cipher key used for messages.
|
||||
const CipherKeyLength = 32
|
||||
|
||||
// MacKeyLength is the length of the message authentication code in bytes.
|
||||
const MacKeyLength = 32
|
||||
|
||||
// IVLength is the length of the initialization vector in bytes.
|
||||
const IVLength = 16
|
||||
|
||||
// KdfSalt is used as the Salt for message keys to derive secrets using a Key Derivation Function
|
||||
const KdfSalt string = "WhisperMessageKeys"
|
||||
|
||||
// NewKeys returns a new message keys structure with the given cipherKey, mac, iv, and index.
|
||||
func NewKeys(cipherKey, macKey, iv []byte, index uint32) *Keys {
|
||||
messageKeys := Keys{
|
||||
cipherKey: cipherKey,
|
||||
macKey: macKey,
|
||||
iv: iv,
|
||||
index: index,
|
||||
}
|
||||
|
||||
return &messageKeys
|
||||
}
|
||||
|
||||
// NewKeysFromStruct will return a new message keys object from the
|
||||
// given serializeable structure.
|
||||
func NewKeysFromStruct(structure *KeysStructure) *Keys {
|
||||
return NewKeys(
|
||||
structure.CipherKey,
|
||||
structure.MacKey,
|
||||
structure.IV,
|
||||
structure.Index,
|
||||
)
|
||||
}
|
||||
|
||||
// NewStructFromKeys returns a serializeable structure of message keys.
|
||||
func NewStructFromKeys(keys *Keys) *KeysStructure {
|
||||
return &KeysStructure{
|
||||
CipherKey: keys.cipherKey,
|
||||
MacKey: keys.macKey,
|
||||
IV: keys.iv,
|
||||
Index: keys.index,
|
||||
}
|
||||
}
|
||||
|
||||
// KeysStructure is a serializeable structure of message keys.
|
||||
type KeysStructure struct {
|
||||
CipherKey []byte
|
||||
MacKey []byte
|
||||
IV []byte
|
||||
Index uint32
|
||||
}
|
||||
|
||||
// Keys is a structure to hold all the keys for a single MessageKey, including the
|
||||
// cipherKey, mac, iv, and index of the chain key. MessageKeys are used to
|
||||
// encrypt individual messages.
|
||||
type Keys struct {
|
||||
cipherKey []byte
|
||||
macKey []byte
|
||||
iv []byte
|
||||
index uint32
|
||||
}
|
||||
|
||||
// CipherKey is the key used to produce ciphertext.
|
||||
func (k *Keys) CipherKey() []byte {
|
||||
return k.cipherKey
|
||||
}
|
||||
|
||||
// MacKey returns the message's message authentication code.
|
||||
func (k *Keys) MacKey() []byte {
|
||||
return k.macKey
|
||||
}
|
||||
|
||||
// Iv returns the message keys' initialization vector. The IV is a fixed-size input
|
||||
// to a cryptographic primitive.
|
||||
func (k *Keys) Iv() []byte {
|
||||
return k.iv
|
||||
}
|
||||
|
||||
// Index returns the number of times the chain key has been put through a key derivation
|
||||
// function to generate this message key.
|
||||
func (k *Keys) Index() uint32 {
|
||||
return k.index
|
||||
}
|
86
vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go
vendored
Normal file
86
vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
// Package prekey provides prekey bundle structures for calculating
|
||||
// a new Signal session with a user asyncronously.
|
||||
package prekey
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewBundle returns a Bundle structure that contains a remote PreKey
|
||||
// and collection of associated items.
|
||||
func NewBundle(registrationID, deviceID uint32, preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
preKeyPublic, signedPreKeyPublic ecc.ECPublicKeyable, signedPreKeySig [64]byte,
|
||||
identityKey *identity.Key) *Bundle {
|
||||
|
||||
bundle := Bundle{
|
||||
registrationID: registrationID,
|
||||
deviceID: deviceID,
|
||||
preKeyID: preKeyID,
|
||||
preKeyPublic: preKeyPublic,
|
||||
signedPreKeyID: signedPreKeyID,
|
||||
signedPreKeyPublic: signedPreKeyPublic,
|
||||
signedPreKeySignature: signedPreKeySig,
|
||||
identityKey: identityKey,
|
||||
}
|
||||
|
||||
return &bundle
|
||||
}
|
||||
|
||||
// Bundle is a structure that contains a remote PreKey and collection
|
||||
// of associated items.
|
||||
type Bundle struct {
|
||||
registrationID uint32
|
||||
deviceID uint32
|
||||
preKeyID *optional.Uint32
|
||||
preKeyPublic ecc.ECPublicKeyable
|
||||
signedPreKeyID uint32
|
||||
signedPreKeyPublic ecc.ECPublicKeyable
|
||||
signedPreKeySignature [64]byte
|
||||
identityKey *identity.Key
|
||||
}
|
||||
|
||||
// DeviceID returns the device ID this PreKey belongs to.
|
||||
func (b *Bundle) DeviceID() uint32 {
|
||||
return b.deviceID
|
||||
}
|
||||
|
||||
// PreKeyID returns the unique key ID for this PreKey.
|
||||
func (b *Bundle) PreKeyID() *optional.Uint32 {
|
||||
return b.preKeyID
|
||||
}
|
||||
|
||||
// PreKey returns the public key for this PreKey.
|
||||
func (b *Bundle) PreKey() ecc.ECPublicKeyable {
|
||||
return b.preKeyPublic
|
||||
}
|
||||
|
||||
// SignedPreKeyID returns the unique key ID for this
|
||||
// signed PreKey.
|
||||
func (b *Bundle) SignedPreKeyID() uint32 {
|
||||
return b.signedPreKeyID
|
||||
}
|
||||
|
||||
// SignedPreKey returns the signed PreKey for this
|
||||
// PreKeyBundle.
|
||||
func (b *Bundle) SignedPreKey() ecc.ECPublicKeyable {
|
||||
return b.signedPreKeyPublic
|
||||
}
|
||||
|
||||
// SignedPreKeySignature returns the signature over the
|
||||
// signed PreKey.
|
||||
func (b *Bundle) SignedPreKeySignature() [64]byte {
|
||||
return b.signedPreKeySignature
|
||||
}
|
||||
|
||||
// IdentityKey returns the Identity Key of this PreKey's owner.
|
||||
func (b *Bundle) IdentityKey() *identity.Key {
|
||||
return b.identityKey
|
||||
}
|
||||
|
||||
// RegistrationID returns the registration ID associated with
|
||||
// this PreKey.
|
||||
func (b *Bundle) RegistrationID() uint32 {
|
||||
return b.registrationID
|
||||
}
|
66
vendor/go.mau.fi/libsignal/keys/root/RootKey.go
vendored
Normal file
66
vendor/go.mau.fi/libsignal/keys/root/RootKey.go
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
// Package root provides root keys which are used to derive new chain and
|
||||
// root keys in a ratcheting session.
|
||||
package root
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/session"
|
||||
)
|
||||
|
||||
// DerivedSecretsSize is the size of the derived secrets for root keys.
|
||||
const DerivedSecretsSize = 64
|
||||
|
||||
// KdfInfo is used as the info for message keys to derive secrets using a Key Derivation Function
|
||||
const KdfInfo string = "WhisperRatchet"
|
||||
|
||||
// NewKey returns a new RootKey given the key derivation function and bytes.
|
||||
func NewKey(kdf kdf.HKDF, key []byte) *Key {
|
||||
rootKey := Key{
|
||||
kdf: kdf,
|
||||
key: key,
|
||||
}
|
||||
|
||||
return &rootKey
|
||||
}
|
||||
|
||||
// Key is a structure for RootKeys, which are used to derive a new set of chain and root
|
||||
// keys for every round trip of messages.
|
||||
type Key struct {
|
||||
kdf kdf.HKDF
|
||||
key []byte
|
||||
}
|
||||
|
||||
// Bytes returns the RootKey in bytes.
|
||||
func (k *Key) Bytes() []byte {
|
||||
return k.key
|
||||
}
|
||||
|
||||
// CreateChain creates a new RootKey and ChainKey from the recipient's ratchet key and our private key.
|
||||
func (k *Key) CreateChain(theirRatchetKey ecc.ECPublicKeyable, ourRatchetKey *ecc.ECKeyPair) (*session.KeyPair, error) {
|
||||
theirPublicKey := theirRatchetKey.PublicKey()
|
||||
ourPrivateKey := ourRatchetKey.PrivateKey().Serialize()
|
||||
|
||||
// Use our key derivation function to calculate a shared secret.
|
||||
sharedSecret := kdf.CalculateSharedSecret(theirPublicKey, ourPrivateKey)
|
||||
derivedSecretBytes, err := kdf.DeriveSecrets(sharedSecret[:], k.key, []byte(KdfInfo), DerivedSecretsSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Split the derived secret bytes in half, using one half for the root key and the second for the chain key.
|
||||
derivedSecrets := session.NewDerivedSecrets(derivedSecretBytes)
|
||||
|
||||
// Create new root and chain key structures from the derived secrets.
|
||||
rootKey := NewKey(k.kdf, derivedSecrets.RootKey())
|
||||
chainKey := chain.NewKey(k.kdf, derivedSecrets.ChainKey(), 0)
|
||||
|
||||
// Create a session keypair with the generated root and chain keys.
|
||||
keyPair := session.NewKeyPair(
|
||||
rootKey,
|
||||
chainKey,
|
||||
)
|
||||
|
||||
return keyPair, nil
|
||||
}
|
29
vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go
vendored
Normal file
29
vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package session
|
||||
|
||||
// NewDerivedSecrets returns a new RootKey/ChainKey pair from 64 bytes of key material
|
||||
// generated by the key derivation function.
|
||||
func NewDerivedSecrets(keyMaterial []byte) *DerivedSecrets {
|
||||
secrets := DerivedSecrets{
|
||||
keyMaterial[:32],
|
||||
keyMaterial[32:],
|
||||
}
|
||||
|
||||
return &secrets
|
||||
}
|
||||
|
||||
// DerivedSecrets is a structure for holding the derived secrets for the
|
||||
// Root and Chain keys for a session.
|
||||
type DerivedSecrets struct {
|
||||
rootKey []byte
|
||||
chainKey []byte
|
||||
}
|
||||
|
||||
// RootKey returns the RootKey bytes.
|
||||
func (d *DerivedSecrets) RootKey() []byte {
|
||||
return d.rootKey
|
||||
}
|
||||
|
||||
// ChainKey returns the ChainKey bytes.
|
||||
func (d *DerivedSecrets) ChainKey() []byte {
|
||||
return d.chainKey
|
||||
}
|
43
vendor/go.mau.fi/libsignal/keys/session/Pair.go
vendored
Normal file
43
vendor/go.mau.fi/libsignal/keys/session/Pair.go
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Package session provides a simple structure for session keys, which is
|
||||
// a pair of root and chain keys for a session.
|
||||
package session
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
)
|
||||
|
||||
// RootKeyable is an interface for all root key implementations that are part of
|
||||
// a session keypair.
|
||||
type RootKeyable interface {
|
||||
Bytes() []byte
|
||||
CreateChain(theirRatchetKey ecc.ECPublicKeyable, ourRatchetKey *ecc.ECKeyPair) (*KeyPair, error)
|
||||
}
|
||||
|
||||
// ChainKeyable is an interface for all chain key implementations that are part of
|
||||
// a session keypair.
|
||||
type ChainKeyable interface {
|
||||
Key() []byte
|
||||
Index() uint32
|
||||
NextKey() *chain.Key
|
||||
MessageKeys() *message.Keys
|
||||
Current() *chain.Key
|
||||
}
|
||||
|
||||
// NewKeyPair returns a new session key pair that holds a root and chain key.
|
||||
func NewKeyPair(rootKey RootKeyable, chainKey ChainKeyable) *KeyPair {
|
||||
keyPair := KeyPair{
|
||||
RootKey: rootKey,
|
||||
ChainKey: chainKey,
|
||||
}
|
||||
|
||||
return &keyPair
|
||||
}
|
||||
|
||||
// KeyPair is a session key pair that holds a single root and chain key pair. These
|
||||
// keys are ratcheted after every message sent and every message round trip.
|
||||
type KeyPair struct {
|
||||
RootKey RootKeyable
|
||||
ChainKey ChainKeyable
|
||||
}
|
85
vendor/go.mau.fi/libsignal/logger/DefaultLogger.go
vendored
Normal file
85
vendor/go.mau.fi/libsignal/logger/DefaultLogger.go
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultLogger is used if no logger has been set up.
|
||||
type defaultLogger struct {
|
||||
namespaces []string
|
||||
}
|
||||
|
||||
// log simply logs the given message to stdout if the message
|
||||
// caller is allowed to log.
|
||||
func (d *defaultLogger) log(level, caller, msg string) {
|
||||
if !d.shouldLog(caller) {
|
||||
// return
|
||||
}
|
||||
t := time.Now()
|
||||
fmt.Println(
|
||||
"["+level+"]",
|
||||
t.Format(time.RFC3339),
|
||||
caller,
|
||||
"▶ ",
|
||||
msg,
|
||||
)
|
||||
}
|
||||
|
||||
// shouldLog determines whether or not the given caller should
|
||||
// be allowed to log messages.
|
||||
func (d *defaultLogger) shouldLog(caller string) bool {
|
||||
shouldLog := false
|
||||
d.ensureNamespaces()
|
||||
for _, namespace := range d.namespaces {
|
||||
if namespace == "all" {
|
||||
shouldLog = true
|
||||
}
|
||||
if strings.Contains(caller, namespace) {
|
||||
shouldLog = true
|
||||
}
|
||||
}
|
||||
|
||||
return shouldLog
|
||||
}
|
||||
|
||||
// ensureNamespaces checks to see if our list of loggable namespaces
|
||||
// has been initialized or not. If not, it defaults to log all.
|
||||
func (d *defaultLogger) ensureNamespaces() {
|
||||
if d.namespaces == nil {
|
||||
d.namespaces = []string{"all"}
|
||||
}
|
||||
}
|
||||
|
||||
// Debug is used to log debug messages.
|
||||
func (d *defaultLogger) Debug(caller, msg string) {
|
||||
//d.log("DEBUG", caller, msg)
|
||||
}
|
||||
|
||||
// Info is used to log info messages.
|
||||
func (d *defaultLogger) Info(caller, msg string) {
|
||||
d.log("INFO", caller, msg)
|
||||
}
|
||||
|
||||
// Warning is used to log warning messages.
|
||||
func (d *defaultLogger) Warning(caller, msg string) {
|
||||
d.log("WARNING", caller, msg)
|
||||
}
|
||||
|
||||
// Error is used to log error messages.
|
||||
func (d *defaultLogger) Error(caller, msg string) {
|
||||
d.log("ERROR", caller, msg)
|
||||
}
|
||||
|
||||
// Configure takes a configuration string separated by commas
|
||||
// that contains all the callers that should be logged. This
|
||||
// allows granular logging of different go files.
|
||||
//
|
||||
// Example:
|
||||
// logger.Configure("RootKey.go,Curve.go")
|
||||
// logger.Configure("all")
|
||||
//
|
||||
func (d *defaultLogger) Configure(settings string) {
|
||||
d.namespaces = strings.Split(settings, ",")
|
||||
}
|
89
vendor/go.mau.fi/libsignal/logger/Logger.go
vendored
Normal file
89
vendor/go.mau.fi/libsignal/logger/Logger.go
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
// Package logger provides optional debug logging of the Signal library.
|
||||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Logger is a shared loggable interface that this library will use for all log messages.
|
||||
var Logger Loggable
|
||||
|
||||
// Loggable is an interface for logging.
|
||||
type Loggable interface {
|
||||
Debug(caller, message string)
|
||||
Info(caller, message string)
|
||||
Warning(caller, message string)
|
||||
Error(caller, message string)
|
||||
Configure(settings string)
|
||||
}
|
||||
|
||||
// Setup will configure the shared logger to use the provided logger.
|
||||
func Setup(logger *Loggable) {
|
||||
Logger = *logger
|
||||
}
|
||||
|
||||
// ToString converts an arbitrary number of objects to a string for use in a logger.
|
||||
func toString(a ...interface{}) string {
|
||||
return fmt.Sprint(a...)
|
||||
}
|
||||
|
||||
// EnsureLogger will use the default logger if one was not set up.
|
||||
func ensureLogger() {
|
||||
if Logger == nil {
|
||||
// fmt.Println("Error: No logger was configured. Use `logger.Setup` to configure a logger.")
|
||||
Logger = &defaultLogger{}
|
||||
}
|
||||
}
|
||||
|
||||
// GetCaller gets the go file name and line number that the logger was called from.
|
||||
func getCaller() string {
|
||||
var file string
|
||||
_, path, line, _ := runtime.Caller(2)
|
||||
paths := strings.Split(path, "/")
|
||||
if len(paths) > 0 {
|
||||
file = paths[len(paths)-1]
|
||||
} else {
|
||||
file = "<unkn>"
|
||||
}
|
||||
|
||||
return file + ":" + strconv.Itoa(line)
|
||||
}
|
||||
|
||||
/*
|
||||
* Go methods used by the library for logging.
|
||||
*/
|
||||
|
||||
// Debug prints debug level logs.
|
||||
func Debug(msg ...interface{}) {
|
||||
ensureLogger()
|
||||
Logger.Debug(getCaller(), toString(msg...))
|
||||
}
|
||||
|
||||
// Info prints info level logs.
|
||||
func Info(msg ...interface{}) {
|
||||
ensureLogger()
|
||||
Logger.Info(getCaller(), toString(msg...))
|
||||
}
|
||||
|
||||
// Warning prints warning level logs.
|
||||
func Warning(msg ...interface{}) {
|
||||
ensureLogger()
|
||||
Logger.Warning(getCaller(), toString(msg...))
|
||||
}
|
||||
|
||||
// Error prints error level logs.
|
||||
func Error(msg ...interface{}) {
|
||||
ensureLogger()
|
||||
Logger.Error(getCaller(), toString(msg...))
|
||||
}
|
||||
|
||||
// Configure allows arbitrary logger configuration settings. The
|
||||
// default logger uses this method to configure what Go files
|
||||
// are allowed to log.
|
||||
func Configure(settings string) {
|
||||
ensureLogger()
|
||||
Logger.Configure(settings)
|
||||
}
|
19
vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go
vendored
Normal file
19
vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
package protocol
|
||||
|
||||
type CiphertextMessage interface {
|
||||
Serialize() []byte
|
||||
Type() uint32
|
||||
}
|
||||
|
||||
type GroupCiphertextMessage interface {
|
||||
CiphertextMessage
|
||||
SignedSerialize() []byte
|
||||
}
|
||||
|
||||
const UnsupportedVersion = 1
|
||||
const CurrentVersion = 3
|
||||
|
||||
const WHISPER_TYPE = 2
|
||||
const PREKEY_TYPE = 3
|
||||
const SENDERKEY_TYPE = 4
|
||||
const SENDERKEY_DISTRIBUTION_TYPE = 5
|
3
vendor/go.mau.fi/libsignal/protocol/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/protocol/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package protocol provides address, group, and message structures that
|
||||
// the Signal protocol uses for sending encrypted messages.
|
||||
package protocol
|
152
vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go
vendored
Normal file
152
vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// PreKeySignalMessageSerializer is an interface for serializing and deserializing
|
||||
// PreKeySignalMessages into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type PreKeySignalMessageSerializer interface {
|
||||
Serialize(signalMessage *PreKeySignalMessageStructure) []byte
|
||||
Deserialize(serialized []byte) (*PreKeySignalMessageStructure, error)
|
||||
}
|
||||
|
||||
// NewPreKeySignalMessageFromBytes will return a Signal Ciphertext message from the given
|
||||
// bytes using the given serializer.
|
||||
func NewPreKeySignalMessageFromBytes(serialized []byte, serializer PreKeySignalMessageSerializer,
|
||||
msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
signalMessageStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewPreKeySignalMessageFromStruct(signalMessageStructure, serializer, msgSerializer)
|
||||
}
|
||||
|
||||
// NewPreKeySignalMessageFromStruct will return a new PreKeySignalMessage from the given
|
||||
// PreKeySignalMessageStructure.
|
||||
func NewPreKeySignalMessageFromStruct(structure *PreKeySignalMessageStructure,
|
||||
serializer PreKeySignalMessageSerializer, msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
|
||||
|
||||
// Throw an error if the given message structure is an unsupported version.
|
||||
if structure.Version <= UnsupportedVersion {
|
||||
return nil, fmt.Errorf("%w %d (prekey message)", signalerror.ErrOldMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the given message structure is a future version.
|
||||
if structure.Version > CurrentVersion {
|
||||
return nil, fmt.Errorf("%w %d (prekey message)", signalerror.ErrUnknownMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the structure is missing critical fields.
|
||||
if structure.BaseKey == nil || structure.IdentityKey == nil || structure.Message == nil {
|
||||
return nil, fmt.Errorf("%w (prekey message)", signalerror.ErrIncompleteMessage)
|
||||
}
|
||||
|
||||
// Create the signal message object from the structure.
|
||||
preKeyWhisperMessage := &PreKeySignalMessage{structure: *structure, serializer: serializer}
|
||||
|
||||
// Generate the base ECC key from bytes.
|
||||
var err error
|
||||
preKeyWhisperMessage.baseKey, err = ecc.DecodePoint(structure.BaseKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate the identity key from bytes
|
||||
var identityKey ecc.ECPublicKeyable
|
||||
identityKey, err = ecc.DecodePoint(structure.IdentityKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
preKeyWhisperMessage.identityKey = identity.NewKey(identityKey)
|
||||
|
||||
// Generate the SignalMessage object from bytes.
|
||||
preKeyWhisperMessage.message, err = NewSignalMessageFromBytes(structure.Message, msgSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return preKeyWhisperMessage, nil
|
||||
}
|
||||
|
||||
// NewPreKeySignalMessage will return a new PreKeySignalMessage object.
|
||||
func NewPreKeySignalMessage(version int, registrationID uint32, preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
baseKey ecc.ECPublicKeyable, identityKey *identity.Key, message *SignalMessage, serializer PreKeySignalMessageSerializer,
|
||||
msgSerializer SignalMessageSerializer) (*PreKeySignalMessage, error) {
|
||||
structure := &PreKeySignalMessageStructure{
|
||||
Version: version,
|
||||
RegistrationID: registrationID,
|
||||
PreKeyID: preKeyID,
|
||||
SignedPreKeyID: signedPreKeyID,
|
||||
BaseKey: baseKey.Serialize(),
|
||||
IdentityKey: identityKey.PublicKey().Serialize(),
|
||||
Message: message.Serialize(),
|
||||
}
|
||||
return NewPreKeySignalMessageFromStruct(structure, serializer, msgSerializer)
|
||||
}
|
||||
|
||||
// PreKeySignalMessageStructure is a serializable structure for
|
||||
// PreKeySignalMessages.
|
||||
type PreKeySignalMessageStructure struct {
|
||||
RegistrationID uint32
|
||||
PreKeyID *optional.Uint32
|
||||
SignedPreKeyID uint32
|
||||
BaseKey []byte
|
||||
IdentityKey []byte
|
||||
Message []byte
|
||||
Version int
|
||||
}
|
||||
|
||||
// PreKeySignalMessage is an encrypted Signal message that is designed
|
||||
// to be used when building a session with someone for the first time.
|
||||
type PreKeySignalMessage struct {
|
||||
structure PreKeySignalMessageStructure
|
||||
baseKey ecc.ECPublicKeyable
|
||||
identityKey *identity.Key
|
||||
message *SignalMessage
|
||||
serializer PreKeySignalMessageSerializer
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) MessageVersion() int {
|
||||
return p.structure.Version
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) IdentityKey() *identity.Key {
|
||||
return p.identityKey
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) RegistrationID() uint32 {
|
||||
return p.structure.RegistrationID
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) PreKeyID() *optional.Uint32 {
|
||||
return p.structure.PreKeyID
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) SignedPreKeyID() uint32 {
|
||||
return p.structure.SignedPreKeyID
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) BaseKey() ecc.ECPublicKeyable {
|
||||
return p.baseKey
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) WhisperMessage() *SignalMessage {
|
||||
return p.message
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) Serialize() []byte {
|
||||
return p.serializer.Serialize(&p.structure)
|
||||
}
|
||||
|
||||
func (p *PreKeySignalMessage) Type() uint32 {
|
||||
return PREKEY_TYPE
|
||||
}
|
147
vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go
vendored
Normal file
147
vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
)
|
||||
|
||||
// SenderKeyDistributionMessageSerializer is an interface for serializing and deserializing
|
||||
// SenderKeyDistributionMessages into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SenderKeyDistributionMessageSerializer interface {
|
||||
Serialize(signalMessage *SenderKeyDistributionMessageStructure) []byte
|
||||
Deserialize(serialized []byte) (*SenderKeyDistributionMessageStructure, error)
|
||||
}
|
||||
|
||||
// NewSenderKeyDistributionMessageFromBytes will return a Signal Ciphertext message from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSenderKeyDistributionMessageFromBytes(serialized []byte,
|
||||
serializer SenderKeyDistributionMessageSerializer) (*SenderKeyDistributionMessage, error) {
|
||||
|
||||
// Use the given serializer to decode the signal message.
|
||||
signalMessageStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSenderKeyDistributionMessageFromStruct(signalMessageStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSenderKeyDistributionMessageFromStruct returns a Signal Ciphertext message from the
|
||||
// given serializable structure.
|
||||
func NewSenderKeyDistributionMessageFromStruct(structure *SenderKeyDistributionMessageStructure,
|
||||
serializer SenderKeyDistributionMessageSerializer) (*SenderKeyDistributionMessage, error) {
|
||||
|
||||
// Throw an error if the given message structure is an unsupported version.
|
||||
if structure.Version <= UnsupportedVersion {
|
||||
return nil, fmt.Errorf("%w %d (sender key distribution)", signalerror.ErrOldMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the given message structure is a future version.
|
||||
if structure.Version > CurrentVersion {
|
||||
return nil, fmt.Errorf("%w %d (sender key distribution)", signalerror.ErrUnknownMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the structure is missing critical fields.
|
||||
if structure.SigningKey == nil || structure.ChainKey == nil {
|
||||
return nil, fmt.Errorf("%w (sender key distribution)", signalerror.ErrIncompleteMessage)
|
||||
}
|
||||
|
||||
// Get the signing key object from bytes.
|
||||
signingKey, err := ecc.DecodePoint(structure.SigningKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create the signal message object from the structure.
|
||||
message := &SenderKeyDistributionMessage{
|
||||
id: structure.ID,
|
||||
iteration: structure.Iteration,
|
||||
chainKey: structure.ChainKey,
|
||||
version: structure.Version,
|
||||
signatureKey: signingKey,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
message.signatureKey, err = ecc.DecodePoint(structure.SigningKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return message, nil
|
||||
}
|
||||
|
||||
// NewSenderKeyDistributionMessage returns a Signal Ciphertext message.
|
||||
func NewSenderKeyDistributionMessage(id uint32, iteration uint32,
|
||||
chainKey []byte, signatureKey ecc.ECPublicKeyable,
|
||||
serializer SenderKeyDistributionMessageSerializer) *SenderKeyDistributionMessage {
|
||||
|
||||
return &SenderKeyDistributionMessage{
|
||||
id: id,
|
||||
iteration: iteration,
|
||||
chainKey: chainKey,
|
||||
signatureKey: signatureKey,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// SenderKeyDistributionMessageStructure is a serializeable structure for senderkey
|
||||
// distribution messages.
|
||||
type SenderKeyDistributionMessageStructure struct {
|
||||
ID uint32
|
||||
Iteration uint32
|
||||
ChainKey []byte
|
||||
SigningKey []byte
|
||||
Version uint32
|
||||
}
|
||||
|
||||
// SenderKeyDistributionMessage is a structure for senderkey distribution messages.
|
||||
type SenderKeyDistributionMessage struct {
|
||||
id uint32
|
||||
iteration uint32
|
||||
chainKey []byte
|
||||
version uint32
|
||||
signatureKey ecc.ECPublicKeyable
|
||||
serializer SenderKeyDistributionMessageSerializer
|
||||
}
|
||||
|
||||
// ID will return the message's id.
|
||||
func (p *SenderKeyDistributionMessage) ID() uint32 {
|
||||
return p.id
|
||||
}
|
||||
|
||||
// Iteration will return the message's iteration.
|
||||
func (p *SenderKeyDistributionMessage) Iteration() uint32 {
|
||||
return p.iteration
|
||||
}
|
||||
|
||||
// ChainKey will return the message's chain key in bytes.
|
||||
func (p *SenderKeyDistributionMessage) ChainKey() []byte {
|
||||
return p.chainKey
|
||||
}
|
||||
|
||||
// SignatureKey will return the message's signature public key
|
||||
func (p *SenderKeyDistributionMessage) SignatureKey() ecc.ECPublicKeyable {
|
||||
return p.signatureKey
|
||||
}
|
||||
|
||||
// Serialize will use the given serializer and return the message as
|
||||
// bytes.
|
||||
func (p *SenderKeyDistributionMessage) Serialize() []byte {
|
||||
structure := &SenderKeyDistributionMessageStructure{
|
||||
ID: p.id,
|
||||
Iteration: p.iteration,
|
||||
ChainKey: p.chainKey,
|
||||
SigningKey: p.signatureKey.Serialize(),
|
||||
Version: CurrentVersion,
|
||||
}
|
||||
return p.serializer.Serialize(structure)
|
||||
}
|
||||
|
||||
// Type will return the message's type.
|
||||
func (p *SenderKeyDistributionMessage) Type() uint32 {
|
||||
return SENDERKEY_DISTRIBUTION_TYPE
|
||||
}
|
168
vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go
vendored
Normal file
168
vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// SenderKeyMessageSerializer is an interface for serializing and deserializing
|
||||
// SenderKeyMessages into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SenderKeyMessageSerializer interface {
|
||||
Serialize(signalMessage *SenderKeyMessageStructure) []byte
|
||||
Deserialize(serialized []byte) (*SenderKeyMessageStructure, error)
|
||||
}
|
||||
|
||||
// NewSenderKeyMessageFromBytes will return a Signal Ciphertext message from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSenderKeyMessageFromBytes(serialized []byte,
|
||||
serializer SenderKeyMessageSerializer) (*SenderKeyMessage, error) {
|
||||
|
||||
// Use the given serializer to decode the signal message.
|
||||
senderKeyMessageStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSenderKeyMessageFromStruct(senderKeyMessageStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSenderKeyMessageFromStruct returns a Signal Ciphertext message from the
|
||||
// given serializable structure.
|
||||
func NewSenderKeyMessageFromStruct(structure *SenderKeyMessageStructure,
|
||||
serializer SenderKeyMessageSerializer) (*SenderKeyMessage, error) {
|
||||
|
||||
// Throw an error if the given message structure is an unsupported version.
|
||||
if structure.Version <= UnsupportedVersion {
|
||||
return nil, fmt.Errorf("%w %d (sender key message)", signalerror.ErrOldMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the given message structure is a future version.
|
||||
if structure.Version > CurrentVersion {
|
||||
return nil, fmt.Errorf("%w %d (sender key message)", signalerror.ErrUnknownMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the structure is missing critical fields.
|
||||
if structure.CipherText == nil {
|
||||
return nil, fmt.Errorf("%w (sender key message)", signalerror.ErrIncompleteMessage)
|
||||
}
|
||||
|
||||
// Create the signal message object from the structure.
|
||||
whisperMessage := &SenderKeyMessage{
|
||||
keyID: structure.ID,
|
||||
version: structure.Version,
|
||||
iteration: structure.Iteration,
|
||||
ciphertext: structure.CipherText,
|
||||
signature: structure.Signature,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return whisperMessage, nil
|
||||
}
|
||||
|
||||
// NewSenderKeyMessage returns a SenderKeyMessage.
|
||||
func NewSenderKeyMessage(keyID uint32, iteration uint32, ciphertext []byte,
|
||||
signatureKey ecc.ECPrivateKeyable, serializer SenderKeyMessageSerializer) *SenderKeyMessage {
|
||||
|
||||
// Ensure we have a valid signature key
|
||||
if signatureKey == nil {
|
||||
panic("Signature is nil. Unable to sign new senderkey message.")
|
||||
}
|
||||
|
||||
// Build our SenderKeyMessage.
|
||||
senderKeyMessage := &SenderKeyMessage{
|
||||
keyID: keyID,
|
||||
iteration: iteration,
|
||||
ciphertext: ciphertext,
|
||||
version: CurrentVersion,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
// Sign the serialized message and include it in the message. This will be included
|
||||
// in the signed serialized version of the message.
|
||||
signature := ecc.CalculateSignature(signatureKey, senderKeyMessage.Serialize())
|
||||
senderKeyMessage.signature = bytehelper.ArrayToSlice64(signature)
|
||||
|
||||
return senderKeyMessage
|
||||
}
|
||||
|
||||
// SenderKeyMessageStructure is a serializeable structure for SenderKey messages.
|
||||
type SenderKeyMessageStructure struct {
|
||||
ID uint32
|
||||
Iteration uint32
|
||||
CipherText []byte
|
||||
Version uint32
|
||||
Signature []byte
|
||||
}
|
||||
|
||||
// SenderKeyMessage is a structure for messages using senderkey groups.
|
||||
type SenderKeyMessage struct {
|
||||
version uint32
|
||||
keyID uint32
|
||||
iteration uint32
|
||||
ciphertext []byte
|
||||
signature []byte
|
||||
serializer SenderKeyMessageSerializer
|
||||
}
|
||||
|
||||
// KeyID returns the SenderKeyMessage key ID.
|
||||
func (p *SenderKeyMessage) KeyID() uint32 {
|
||||
return p.keyID
|
||||
}
|
||||
|
||||
// Iteration returns the SenderKeyMessage iteration.
|
||||
func (p *SenderKeyMessage) Iteration() uint32 {
|
||||
return p.iteration
|
||||
}
|
||||
|
||||
// Ciphertext returns the SenderKeyMessage encrypted ciphertext.
|
||||
func (p *SenderKeyMessage) Ciphertext() []byte {
|
||||
return p.ciphertext
|
||||
}
|
||||
|
||||
// Version returns the Signal message version of the message.
|
||||
func (p *SenderKeyMessage) Version() uint32 {
|
||||
return p.version
|
||||
}
|
||||
|
||||
// Serialize will use the given serializer to return the message as bytes
|
||||
// excluding the signature. This should be used for signing and verifying
|
||||
// message signatures.
|
||||
func (p *SenderKeyMessage) Serialize() []byte {
|
||||
structure := &SenderKeyMessageStructure{
|
||||
ID: p.keyID,
|
||||
Iteration: p.iteration,
|
||||
CipherText: p.ciphertext,
|
||||
Version: p.version,
|
||||
}
|
||||
|
||||
return p.serializer.Serialize(structure)
|
||||
}
|
||||
|
||||
// SignedSerialize will use the given serializer to return the message as
|
||||
// bytes with the message signature included. This should be used when
|
||||
// sending the message over the network.
|
||||
func (p *SenderKeyMessage) SignedSerialize() []byte {
|
||||
structure := &SenderKeyMessageStructure{
|
||||
ID: p.keyID,
|
||||
Iteration: p.iteration,
|
||||
CipherText: p.ciphertext,
|
||||
Version: p.version,
|
||||
Signature: p.signature,
|
||||
}
|
||||
|
||||
return p.serializer.Serialize(structure)
|
||||
}
|
||||
|
||||
// Signature returns the SenderKeyMessage signature
|
||||
func (p *SenderKeyMessage) Signature() [64]byte {
|
||||
return bytehelper.SliceToArray64(p.signature)
|
||||
}
|
||||
|
||||
// Type returns the sender key type.
|
||||
func (p *SenderKeyMessage) Type() uint32 {
|
||||
return SENDERKEY_TYPE
|
||||
}
|
25
vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go
vendored
Normal file
25
vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package protocol
|
||||
|
||||
// NewSenderKeyName returns a new SenderKeyName object.
|
||||
func NewSenderKeyName(groupID string, sender *SignalAddress) *SenderKeyName {
|
||||
return &SenderKeyName{
|
||||
groupID: groupID,
|
||||
sender: sender,
|
||||
}
|
||||
}
|
||||
|
||||
// SenderKeyName is a structure for a group session address.
|
||||
type SenderKeyName struct {
|
||||
groupID string
|
||||
sender *SignalAddress
|
||||
}
|
||||
|
||||
// GroupID returns the sender key group id
|
||||
func (n *SenderKeyName) GroupID() string {
|
||||
return n.groupID
|
||||
}
|
||||
|
||||
// Sender returns the Signal address of sending user in the group.
|
||||
func (n *SenderKeyName) Sender() *SignalAddress {
|
||||
return n.sender
|
||||
}
|
226
vendor/go.mau.fi/libsignal/protocol/SignalMessage.go
vendored
Normal file
226
vendor/go.mau.fi/libsignal/protocol/SignalMessage.go
vendored
Normal file
@ -0,0 +1,226 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
const MacLength int = 8
|
||||
|
||||
// SignalMessageSerializer is an interface for serializing and deserializing
|
||||
// SignalMessages into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SignalMessageSerializer interface {
|
||||
Serialize(signalMessage *SignalMessageStructure) []byte
|
||||
Deserialize(serialized []byte) (*SignalMessageStructure, error)
|
||||
}
|
||||
|
||||
// NewSignalMessageFromBytes will return a Signal Ciphertext message from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSignalMessageFromBytes(serialized []byte, serializer SignalMessageSerializer) (*SignalMessage, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
signalMessageStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSignalMessageFromStruct(signalMessageStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSignalMessageFromStruct returns a Signal Ciphertext message from the
|
||||
// given serializable structure.
|
||||
func NewSignalMessageFromStruct(structure *SignalMessageStructure, serializer SignalMessageSerializer) (*SignalMessage, error) {
|
||||
// Throw an error if the given message structure is an unsupported version.
|
||||
if structure.Version <= UnsupportedVersion {
|
||||
return nil, fmt.Errorf("%w %d (normal message)", signalerror.ErrOldMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the given message structure is a future version.
|
||||
if structure.Version > CurrentVersion {
|
||||
return nil, fmt.Errorf("%w %d (normal message)", signalerror.ErrUnknownMessageVersion, structure.Version)
|
||||
}
|
||||
|
||||
// Throw an error if the structure is missing critical fields.
|
||||
if structure.CipherText == nil || structure.RatchetKey == nil {
|
||||
return nil, fmt.Errorf("%w (normal message)", signalerror.ErrIncompleteMessage)
|
||||
}
|
||||
|
||||
// Create the signal message object from the structure.
|
||||
whisperMessage := &SignalMessage{structure: *structure, serializer: serializer}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
var err error
|
||||
whisperMessage.senderRatchetKey, err = ecc.DecodePoint(structure.RatchetKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return whisperMessage, nil
|
||||
}
|
||||
|
||||
// NewSignalMessage returns a Signal Ciphertext message.
|
||||
func NewSignalMessage(messageVersion int, counter, previousCounter uint32, macKey []byte,
|
||||
senderRatchetKey ecc.ECPublicKeyable, ciphertext []byte, senderIdentityKey,
|
||||
receiverIdentityKey *identity.Key, serializer SignalMessageSerializer) (*SignalMessage, error) {
|
||||
|
||||
version := []byte(strconv.Itoa(messageVersion))
|
||||
// Build the signal message structure with the given data.
|
||||
structure := &SignalMessageStructure{
|
||||
Counter: counter,
|
||||
PreviousCounter: previousCounter,
|
||||
RatchetKey: senderRatchetKey.Serialize(),
|
||||
CipherText: ciphertext,
|
||||
}
|
||||
|
||||
serialized := append(version, serializer.Serialize(structure)...)
|
||||
// Get the message authentication code from the serialized structure.
|
||||
mac, err := getMac(
|
||||
messageVersion, senderIdentityKey, receiverIdentityKey,
|
||||
macKey, serialized,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
structure.Mac = mac
|
||||
structure.Version = messageVersion
|
||||
|
||||
// Generate a SignalMessage with the structure.
|
||||
whisperMessage, err := NewSignalMessageFromStruct(structure, serializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return whisperMessage, nil
|
||||
}
|
||||
|
||||
// SignalMessageStructure is a serializeable structure of a signal message
|
||||
// object.
|
||||
type SignalMessageStructure struct {
|
||||
RatchetKey []byte
|
||||
Counter uint32
|
||||
PreviousCounter uint32
|
||||
CipherText []byte
|
||||
Version int
|
||||
Mac []byte
|
||||
}
|
||||
|
||||
// SignalMessage is a cipher message that contains a message encrypted
|
||||
// with the Signal protocol.
|
||||
type SignalMessage struct {
|
||||
structure SignalMessageStructure
|
||||
senderRatchetKey ecc.ECPublicKeyable
|
||||
serializer SignalMessageSerializer
|
||||
}
|
||||
|
||||
// SenderRatchetKey returns the SignalMessage's sender ratchet key. This
|
||||
// key is used for ratcheting the chain forward to negotiate a new shared
|
||||
// secret that cannot be derived from previous chains.
|
||||
func (s *SignalMessage) SenderRatchetKey() ecc.ECPublicKeyable {
|
||||
return s.senderRatchetKey
|
||||
}
|
||||
|
||||
// MessageVersion returns the message version this SignalMessage supports.
|
||||
func (s *SignalMessage) MessageVersion() int {
|
||||
return s.structure.Version
|
||||
}
|
||||
|
||||
// Counter will return the SignalMessage counter.
|
||||
func (s *SignalMessage) Counter() uint32 {
|
||||
return s.structure.Counter
|
||||
}
|
||||
|
||||
// Body will return the SignalMessage's ciphertext in bytes.
|
||||
func (s *SignalMessage) Body() []byte {
|
||||
return s.structure.CipherText
|
||||
}
|
||||
|
||||
// VerifyMac will return an error if the message's message authentication code
|
||||
// is invalid. This should be used on SignalMessages that have been constructed
|
||||
// from a sent message.
|
||||
func (s *SignalMessage) VerifyMac(messageVersion int, senderIdentityKey,
|
||||
receiverIdentityKey *identity.Key, macKey []byte) error {
|
||||
|
||||
// Create a copy of the message without the mac. We'll use this to calculate
|
||||
// the message authentication code.
|
||||
structure := s.structure
|
||||
signalMessage, err := NewSignalMessageFromStruct(&structure, s.serializer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signalMessage.structure.Mac = nil
|
||||
signalMessage.structure.Version = 0
|
||||
version := []byte(strconv.Itoa(s.MessageVersion()))
|
||||
serialized := append(version, signalMessage.Serialize()...)
|
||||
|
||||
// Calculate the message authentication code from the serialized structure.
|
||||
ourMac, err := getMac(
|
||||
messageVersion,
|
||||
senderIdentityKey,
|
||||
receiverIdentityKey,
|
||||
macKey,
|
||||
serialized,
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Get the message authentication code that was sent to us as part of
|
||||
// the signal message structure.
|
||||
theirMac := s.structure.Mac
|
||||
|
||||
logger.Debug("Verifying macs...")
|
||||
logger.Debug(" Our MAC: ", ourMac)
|
||||
logger.Debug(" Their MAC: ", theirMac)
|
||||
|
||||
// Return an error if our calculated mac doesn't match the mac sent to us.
|
||||
if !hmac.Equal(ourMac, theirMac) {
|
||||
return signalerror.ErrBadMAC
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serialize will return the Signal Message as bytes.
|
||||
func (s *SignalMessage) Serialize() []byte {
|
||||
return s.serializer.Serialize(&s.structure)
|
||||
}
|
||||
|
||||
// Structure will return a serializeable structure of the Signal Message.
|
||||
func (s *SignalMessage) Structure() *SignalMessageStructure {
|
||||
structure := s.structure
|
||||
return &structure
|
||||
}
|
||||
|
||||
// Type will return the type of Signal Message this is.
|
||||
func (s *SignalMessage) Type() uint32 {
|
||||
return WHISPER_TYPE
|
||||
}
|
||||
|
||||
// getMac will calculate the mac using the given message version, identity
|
||||
// keys, macKey and SignalMessageStructure. The MAC key is a private key held
|
||||
// by both parties that is concatenated with the message and hashed.
|
||||
func getMac(messageVersion int, senderIdentityKey, receiverIdentityKey *identity.Key,
|
||||
macKey, serialized []byte) ([]byte, error) {
|
||||
|
||||
mac := hmac.New(sha256.New, macKey[:])
|
||||
|
||||
if messageVersion >= 3 {
|
||||
mac.Write(senderIdentityKey.PublicKey().Serialize())
|
||||
mac.Write(receiverIdentityKey.PublicKey().Serialize())
|
||||
}
|
||||
|
||||
mac.Write(serialized)
|
||||
|
||||
fullMac := mac.Sum(nil)
|
||||
|
||||
return bytehelper.Trim(fullMac, MacLength), nil
|
||||
}
|
38
vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go
vendored
Normal file
38
vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const ADDRESS_SEPARATOR = ":"
|
||||
|
||||
// NewSignalAddress returns a new signal address.
|
||||
func NewSignalAddress(name string, deviceID uint32) *SignalAddress {
|
||||
addr := SignalAddress{
|
||||
name: name,
|
||||
deviceID: deviceID,
|
||||
}
|
||||
|
||||
return &addr
|
||||
}
|
||||
|
||||
// SignalAddress is a combination of a name and a device ID.
|
||||
type SignalAddress struct {
|
||||
name string
|
||||
deviceID uint32
|
||||
}
|
||||
|
||||
// Name returns the signal address's name.
|
||||
func (s *SignalAddress) Name() string {
|
||||
return s.name
|
||||
}
|
||||
|
||||
// DeviceID returns the signal address's device ID.
|
||||
func (s *SignalAddress) DeviceID() uint32 {
|
||||
return s.deviceID
|
||||
}
|
||||
|
||||
// String returns a string of both the address name and device id.
|
||||
func (s *SignalAddress) String() string {
|
||||
return fmt.Sprintf("%s%s%d", s.name, ADDRESS_SEPARATOR, s.deviceID)
|
||||
}
|
197
vendor/go.mau.fi/libsignal/ratchet/Ratchet.go
vendored
Normal file
197
vendor/go.mau.fi/libsignal/ratchet/Ratchet.go
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
// Package ratchet provides the methods necessary to establish a new double
|
||||
// ratchet session.
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/root"
|
||||
"go.mau.fi/libsignal/keys/session"
|
||||
)
|
||||
|
||||
var b64 = base64.StdEncoding.EncodeToString
|
||||
|
||||
func genDiscontinuity() [32]byte {
|
||||
var discontinuity [32]byte
|
||||
for i := range discontinuity {
|
||||
discontinuity[i] = 0xFF
|
||||
}
|
||||
return discontinuity
|
||||
}
|
||||
|
||||
// CalculateSenderSession calculates the key agreement for a recipient. This
|
||||
// should be used when we are trying to send a message to someone for the
|
||||
// first time.
|
||||
func CalculateSenderSession(parameters *SenderParameters) (*session.KeyPair, error) {
|
||||
var secret [32]byte
|
||||
var publicKey [32]byte
|
||||
var privateKey [32]byte
|
||||
masterSecret := []byte{} // Create a master shared secret that is 5 different 32-byte values
|
||||
discontinuity := genDiscontinuity()
|
||||
masterSecret = append(masterSecret, discontinuity[:]...)
|
||||
|
||||
// Calculate the agreement using their signed prekey and our identity key.
|
||||
publicKey = parameters.TheirSignedPreKey().PublicKey()
|
||||
privateKey = parameters.OurIdentityKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// Calculate the agreement using their identity key and our base key.
|
||||
publicKey = parameters.TheirIdentityKey().PublicKey().PublicKey()
|
||||
privateKey = parameters.OurBaseKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// Calculate the agreement using their signed prekey and our base key.
|
||||
publicKey = parameters.TheirSignedPreKey().PublicKey()
|
||||
privateKey = parameters.OurBaseKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// If they have a one-time prekey, use it to calculate the shared secret with their
|
||||
// one time key and our base key.
|
||||
if parameters.TheirOneTimePreKey() != nil {
|
||||
publicKey = parameters.TheirOneTimePreKey().PublicKey()
|
||||
privateKey = parameters.OurBaseKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
}
|
||||
|
||||
// Derive the root and chain keys based on the master secret.
|
||||
derivedKeysBytes, err := kdf.DeriveSecrets(masterSecret, nil, []byte("WhisperText"), root.DerivedSecretsSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
derivedKeys := session.NewDerivedSecrets(derivedKeysBytes)
|
||||
chainKey := chain.NewKey(kdf.DeriveSecrets, derivedKeys.ChainKey(), 0)
|
||||
rootKey := root.NewKey(kdf.DeriveSecrets, derivedKeys.RootKey())
|
||||
|
||||
// Add the root and chain keys to a structure that will hold both keys.
|
||||
sessionKeys := session.NewKeyPair(rootKey, chainKey)
|
||||
|
||||
return sessionKeys, nil
|
||||
}
|
||||
|
||||
// CalculateReceiverSession calculates the key agreement for a sender. This should
|
||||
// be used when we are receiving a message from someone for the first time.
|
||||
func CalculateReceiverSession(parameters *ReceiverParameters) (*session.KeyPair, error) {
|
||||
var secret [32]byte
|
||||
var publicKey [32]byte
|
||||
var privateKey [32]byte
|
||||
masterSecret := []byte{} // Create a master shared secret that is 5 different 32-byte values
|
||||
|
||||
discontinuity := genDiscontinuity()
|
||||
masterSecret = append(masterSecret, discontinuity[:]...)
|
||||
|
||||
// Calculate the agreement using their identity key and our signed pre key.
|
||||
publicKey = parameters.TheirIdentityKey().PublicKey().PublicKey()
|
||||
privateKey = parameters.OurSignedPreKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// Calculate the agreement using their base key and our identity key.
|
||||
publicKey = parameters.TheirBaseKey().PublicKey()
|
||||
privateKey = parameters.OurIdentityKeyPair().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// Calculate the agreement using their base key and our signed prekey.
|
||||
publicKey = parameters.TheirBaseKey().PublicKey()
|
||||
privateKey = parameters.OurSignedPreKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
// If we had a one-time prekey, use it to calculate the shared secret with our
|
||||
// one time key and their base key.
|
||||
if parameters.OurOneTimePreKey() != nil {
|
||||
publicKey = parameters.TheirBaseKey().PublicKey()
|
||||
privateKey = parameters.OurOneTimePreKey().PrivateKey().Serialize()
|
||||
secret = kdf.CalculateSharedSecret(
|
||||
publicKey,
|
||||
privateKey,
|
||||
)
|
||||
masterSecret = append(masterSecret, secret[:]...)
|
||||
|
||||
}
|
||||
|
||||
// Derive the root and chain keys based on the master secret.
|
||||
derivedKeysBytes, err := kdf.DeriveSecrets(masterSecret, nil, []byte("WhisperText"), root.DerivedSecretsSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
derivedKeys := session.NewDerivedSecrets(derivedKeysBytes)
|
||||
chainKey := chain.NewKey(kdf.DeriveSecrets, derivedKeys.ChainKey(), 0)
|
||||
rootKey := root.NewKey(kdf.DeriveSecrets, derivedKeys.RootKey())
|
||||
|
||||
// Add the root and chain keys to a structure that will hold both keys.
|
||||
sessionKeys := session.NewKeyPair(rootKey, chainKey)
|
||||
|
||||
return sessionKeys, nil
|
||||
}
|
||||
|
||||
// CalculateSymmetricSession calculates the key agreement between two users. This
|
||||
// works by both clients exchanging KeyExchange messages to first establish a session.
|
||||
// This is useful for establishing a session if both users are online.
|
||||
func CalculateSymmetricSession(parameters *SymmetricParameters) (*session.KeyPair, error) {
|
||||
// Compare the base public keys so we can deterministically know whether we should
|
||||
// be setting up a sender or receiver session. If our key converted to an integer is
|
||||
// less than the other user's, act as a sender.
|
||||
if isSender(parameters.OurBaseKey.PublicKey(), parameters.TheirBaseKey) {
|
||||
senderParameters := &SenderParameters{
|
||||
ourBaseKey: parameters.OurBaseKey,
|
||||
ourIdentityKeyPair: parameters.OurIdentityKeyPair,
|
||||
theirRatchetKey: parameters.TheirRatchetKey,
|
||||
theirIdentityKey: parameters.TheirIdentityKey,
|
||||
theirSignedPreKey: parameters.TheirBaseKey,
|
||||
}
|
||||
|
||||
return CalculateSenderSession(senderParameters)
|
||||
}
|
||||
|
||||
// If our base public key was larger than the other user's, act as a receiver.
|
||||
receiverParameters := &ReceiverParameters{
|
||||
ourIdentityKeyPair: parameters.OurIdentityKeyPair,
|
||||
ourRatchetKey: parameters.OurRatchetKey,
|
||||
ourSignedPreKey: parameters.OurBaseKey,
|
||||
theirBaseKey: parameters.TheirBaseKey,
|
||||
theirIdentityKey: parameters.TheirIdentityKey,
|
||||
}
|
||||
|
||||
return CalculateReceiverSession(receiverParameters)
|
||||
}
|
||||
|
||||
// isSender is a private method for determining if a symmetric session should
|
||||
// be calculated as the sender or receiver. It does so by converting the given
|
||||
// keys into integers and comparing the size of those integers.
|
||||
func isSender(ourKey, theirKey ecc.ECPublicKeyable) bool {
|
||||
ourKeyInt := binary.BigEndian.Uint32(ourKey.Serialize())
|
||||
theirKeyInt := binary.BigEndian.Uint32(theirKey.Serialize())
|
||||
|
||||
return ourKeyInt < theirKeyInt
|
||||
}
|
106
vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go
vendored
Normal file
106
vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
)
|
||||
|
||||
// NewReceiverParameters creates a structure with all the keys needed to construct
|
||||
// a new session when we are receiving a message from a user for the first time.
|
||||
func NewReceiverParameters(ourIdentityKey *identity.KeyPair, ourSignedPreKey *ecc.ECKeyPair,
|
||||
ourOneTimePreKey *ecc.ECKeyPair, ourRatchetKey *ecc.ECKeyPair,
|
||||
theirBaseKey ecc.ECPublicKeyable, theirIdentityKey *identity.Key) *ReceiverParameters {
|
||||
|
||||
receiverParams := ReceiverParameters{
|
||||
ourIdentityKeyPair: ourIdentityKey,
|
||||
ourSignedPreKey: ourSignedPreKey,
|
||||
ourOneTimePreKey: ourOneTimePreKey,
|
||||
ourRatchetKey: ourRatchetKey,
|
||||
theirBaseKey: theirBaseKey,
|
||||
theirIdentityKey: theirIdentityKey,
|
||||
}
|
||||
|
||||
return &receiverParams
|
||||
}
|
||||
|
||||
// NewEmptyReceiverParameters creates an empty structure with the receiver parameters
|
||||
// needed to create a session. You should use the `set` functions to set all the
|
||||
// necessary keys needed to build a session.
|
||||
func NewEmptyReceiverParameters() *ReceiverParameters {
|
||||
receiverParams := ReceiverParameters{}
|
||||
|
||||
return &receiverParams
|
||||
}
|
||||
|
||||
// ReceiverParameters describes the session parameters if we are receiving
|
||||
// a message from someone for the first time. These parameters are used as
|
||||
// the basis for deriving a shared secret with the sender.
|
||||
type ReceiverParameters struct {
|
||||
ourIdentityKeyPair *identity.KeyPair
|
||||
ourSignedPreKey *ecc.ECKeyPair
|
||||
ourOneTimePreKey *ecc.ECKeyPair
|
||||
ourRatchetKey *ecc.ECKeyPair
|
||||
|
||||
theirBaseKey ecc.ECPublicKeyable
|
||||
theirIdentityKey *identity.Key
|
||||
}
|
||||
|
||||
// OurIdentityKeyPair returns the identity key of the receiver.
|
||||
func (r *ReceiverParameters) OurIdentityKeyPair() *identity.KeyPair {
|
||||
return r.ourIdentityKeyPair
|
||||
}
|
||||
|
||||
// OurSignedPreKey returns the signed prekey of the receiver.
|
||||
func (r *ReceiverParameters) OurSignedPreKey() *ecc.ECKeyPair {
|
||||
return r.ourSignedPreKey
|
||||
}
|
||||
|
||||
// OurOneTimePreKey returns the one time prekey of the receiver.
|
||||
func (r *ReceiverParameters) OurOneTimePreKey() *ecc.ECKeyPair {
|
||||
return r.ourOneTimePreKey
|
||||
}
|
||||
|
||||
// OurRatchetKey returns the ratchet key of the receiver.
|
||||
func (r *ReceiverParameters) OurRatchetKey() *ecc.ECKeyPair {
|
||||
return r.ourRatchetKey
|
||||
}
|
||||
|
||||
// TheirBaseKey returns the base key of the sender.
|
||||
func (r *ReceiverParameters) TheirBaseKey() ecc.ECPublicKeyable {
|
||||
return r.theirBaseKey
|
||||
}
|
||||
|
||||
// TheirIdentityKey returns the identity key of the sender.
|
||||
func (r *ReceiverParameters) TheirIdentityKey() *identity.Key {
|
||||
return r.theirIdentityKey
|
||||
}
|
||||
|
||||
// SetOurIdentityKeyPair sets the identity key of the receiver.
|
||||
func (r *ReceiverParameters) SetOurIdentityKeyPair(ourIdentityKey *identity.KeyPair) {
|
||||
r.ourIdentityKeyPair = ourIdentityKey
|
||||
}
|
||||
|
||||
// SetOurSignedPreKey sets the signed prekey of the receiver.
|
||||
func (r *ReceiverParameters) SetOurSignedPreKey(ourSignedPreKey *ecc.ECKeyPair) {
|
||||
r.ourSignedPreKey = ourSignedPreKey
|
||||
}
|
||||
|
||||
// SetOurOneTimePreKey sets the one time prekey of the receiver.
|
||||
func (r *ReceiverParameters) SetOurOneTimePreKey(ourOneTimePreKey *ecc.ECKeyPair) {
|
||||
r.ourOneTimePreKey = ourOneTimePreKey
|
||||
}
|
||||
|
||||
// SetOurRatchetKey sets the ratchet key of the receiver.
|
||||
func (r *ReceiverParameters) SetOurRatchetKey(ourRatchetKey *ecc.ECKeyPair) {
|
||||
r.ourRatchetKey = ourRatchetKey
|
||||
}
|
||||
|
||||
// SetTheirBaseKey sets the base key of the sender.
|
||||
func (r *ReceiverParameters) SetTheirBaseKey(theirBaseKey ecc.ECPublicKeyable) {
|
||||
r.theirBaseKey = theirBaseKey
|
||||
}
|
||||
|
||||
// SetTheirIdentityKey sets the identity key of the sender.
|
||||
func (r *ReceiverParameters) SetTheirIdentityKey(theirIdentityKey *identity.Key) {
|
||||
r.theirIdentityKey = theirIdentityKey
|
||||
}
|
106
vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go
vendored
Normal file
106
vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
)
|
||||
|
||||
// NewSenderParameters creates a structure with all the keys needed to construct
|
||||
// a new session when we are sending a message to a recipient for the first time.
|
||||
func NewSenderParameters(ourIdentityKey *identity.KeyPair, ourBaseKey *ecc.ECKeyPair,
|
||||
theirIdentityKey *identity.Key, theirSignedPreKey ecc.ECPublicKeyable,
|
||||
theirRatchetKey ecc.ECPublicKeyable, theirOneTimePreKey ecc.ECPublicKeyable) *SenderParameters {
|
||||
|
||||
senderParams := SenderParameters{
|
||||
ourIdentityKeyPair: ourIdentityKey,
|
||||
ourBaseKey: ourBaseKey,
|
||||
theirIdentityKey: theirIdentityKey,
|
||||
theirSignedPreKey: theirSignedPreKey,
|
||||
theirOneTimePreKey: theirOneTimePreKey,
|
||||
theirRatchetKey: theirRatchetKey,
|
||||
}
|
||||
|
||||
return &senderParams
|
||||
}
|
||||
|
||||
// NewEmptySenderParameters creates an empty structure with the sender parameters
|
||||
// needed to create a session. You should use the `set` functions to set all the
|
||||
// necessary keys needed to build a session.
|
||||
func NewEmptySenderParameters() *SenderParameters {
|
||||
senderParams := SenderParameters{}
|
||||
|
||||
return &senderParams
|
||||
}
|
||||
|
||||
// SenderParameters describes the session parameters if we are sending the
|
||||
// recipient a message for the first time. These parameters are used as the
|
||||
// basis for deriving a shared secret with a recipient.
|
||||
type SenderParameters struct {
|
||||
ourIdentityKeyPair *identity.KeyPair
|
||||
ourBaseKey *ecc.ECKeyPair
|
||||
|
||||
theirIdentityKey *identity.Key
|
||||
theirSignedPreKey ecc.ECPublicKeyable
|
||||
theirOneTimePreKey ecc.ECPublicKeyable
|
||||
theirRatchetKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// OurIdentityKey returns the identity key pair of the sender.
|
||||
func (s *SenderParameters) OurIdentityKey() *identity.KeyPair {
|
||||
return s.ourIdentityKeyPair
|
||||
}
|
||||
|
||||
// OurBaseKey returns the base ECC key pair of the sender.
|
||||
func (s *SenderParameters) OurBaseKey() *ecc.ECKeyPair {
|
||||
return s.ourBaseKey
|
||||
}
|
||||
|
||||
// TheirIdentityKey returns the identity public key of the receiver.
|
||||
func (s *SenderParameters) TheirIdentityKey() *identity.Key {
|
||||
return s.theirIdentityKey
|
||||
}
|
||||
|
||||
// TheirSignedPreKey returns the signed pre key of the receiver.
|
||||
func (s *SenderParameters) TheirSignedPreKey() ecc.ECPublicKeyable {
|
||||
return s.theirSignedPreKey
|
||||
}
|
||||
|
||||
// TheirOneTimePreKey returns the receiver's one time prekey.
|
||||
func (s *SenderParameters) TheirOneTimePreKey() ecc.ECPublicKeyable {
|
||||
return s.theirOneTimePreKey
|
||||
}
|
||||
|
||||
// TheirRatchetKey returns the receiver's ratchet key.
|
||||
func (s *SenderParameters) TheirRatchetKey() ecc.ECPublicKeyable {
|
||||
return s.theirRatchetKey
|
||||
}
|
||||
|
||||
// SetOurIdentityKey sets the identity key pair of the sender.
|
||||
func (s *SenderParameters) SetOurIdentityKey(ourIdentityKey *identity.KeyPair) {
|
||||
s.ourIdentityKeyPair = ourIdentityKey
|
||||
}
|
||||
|
||||
// SetOurBaseKey sets the base ECC key pair of the sender.
|
||||
func (s *SenderParameters) SetOurBaseKey(ourBaseKey *ecc.ECKeyPair) {
|
||||
s.ourBaseKey = ourBaseKey
|
||||
}
|
||||
|
||||
// SetTheirIdentityKey sets the identity public key of the receiver.
|
||||
func (s *SenderParameters) SetTheirIdentityKey(theirIdentityKey *identity.Key) {
|
||||
s.theirIdentityKey = theirIdentityKey
|
||||
}
|
||||
|
||||
// SetTheirSignedPreKey sets the signed pre key of the receiver.
|
||||
func (s *SenderParameters) SetTheirSignedPreKey(theirSignedPreKey ecc.ECPublicKeyable) {
|
||||
s.theirSignedPreKey = theirSignedPreKey
|
||||
}
|
||||
|
||||
// SetTheirOneTimePreKey sets the receiver's one time prekey.
|
||||
func (s *SenderParameters) SetTheirOneTimePreKey(theirOneTimePreKey ecc.ECPublicKeyable) {
|
||||
s.theirOneTimePreKey = theirOneTimePreKey
|
||||
}
|
||||
|
||||
// SetTheirRatchetKey sets the receiver's ratchet key.
|
||||
func (s *SenderParameters) SetTheirRatchetKey(theirRatchetKey ecc.ECPublicKeyable) {
|
||||
s.theirRatchetKey = theirRatchetKey
|
||||
}
|
18
vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go
vendored
Normal file
18
vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
package ratchet
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
)
|
||||
|
||||
// SymmetricParameters describes the session parameters for sessions where
|
||||
// both users are online, which doesn't use prekeys for setup.
|
||||
type SymmetricParameters struct {
|
||||
OurBaseKey *ecc.ECKeyPair
|
||||
OurRatchetKey *ecc.ECKeyPair
|
||||
OurIdentityKeyPair *identity.KeyPair
|
||||
|
||||
TheirBaseKey ecc.ECPublicKeyable
|
||||
TheirRatchetKey ecc.ECPublicKeyable
|
||||
TheirIdentityKey *identity.Key
|
||||
}
|
245
vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go
vendored
Normal file
245
vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go
vendored
Normal file
@ -0,0 +1,245 @@
|
||||
// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/FingerprintProtocol.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.4
|
||||
// source: serialize/FingerprintProtocol.proto
|
||||
|
||||
package serialize
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type LogicalFingerprint struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Content []byte `protobuf:"bytes,1,opt,name=content" json:"content,omitempty"`
|
||||
Identifier []byte `protobuf:"bytes,2,opt,name=identifier" json:"identifier,omitempty"` // Version 0
|
||||
}
|
||||
|
||||
func (x *LogicalFingerprint) Reset() {
|
||||
*x = LogicalFingerprint{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_FingerprintProtocol_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *LogicalFingerprint) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LogicalFingerprint) ProtoMessage() {}
|
||||
|
||||
func (x *LogicalFingerprint) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_FingerprintProtocol_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use LogicalFingerprint.ProtoReflect.Descriptor instead.
|
||||
func (*LogicalFingerprint) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_FingerprintProtocol_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *LogicalFingerprint) GetContent() []byte {
|
||||
if x != nil {
|
||||
return x.Content
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *LogicalFingerprint) GetIdentifier() []byte {
|
||||
if x != nil {
|
||||
return x.Identifier
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type CombinedFingerprints struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Version *uint32 `protobuf:"varint,1,opt,name=version" json:"version,omitempty"`
|
||||
LocalFingerprint *LogicalFingerprint `protobuf:"bytes,2,opt,name=localFingerprint" json:"localFingerprint,omitempty"`
|
||||
RemoteFingerprint *LogicalFingerprint `protobuf:"bytes,3,opt,name=remoteFingerprint" json:"remoteFingerprint,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CombinedFingerprints) Reset() {
|
||||
*x = CombinedFingerprints{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_FingerprintProtocol_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *CombinedFingerprints) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CombinedFingerprints) ProtoMessage() {}
|
||||
|
||||
func (x *CombinedFingerprints) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_FingerprintProtocol_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use CombinedFingerprints.ProtoReflect.Descriptor instead.
|
||||
func (*CombinedFingerprints) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_FingerprintProtocol_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *CombinedFingerprints) GetVersion() uint32 {
|
||||
if x != nil && x.Version != nil {
|
||||
return *x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CombinedFingerprints) GetLocalFingerprint() *LogicalFingerprint {
|
||||
if x != nil {
|
||||
return x.LocalFingerprint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CombinedFingerprints) GetRemoteFingerprint() *LogicalFingerprint {
|
||||
if x != nil {
|
||||
return x.RemoteFingerprint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_serialize_FingerprintProtocol_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_serialize_FingerprintProtocol_proto_rawDesc = []byte{
|
||||
0x0a, 0x23, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x2f, 0x46, 0x69, 0x6e, 0x67,
|
||||
0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72,
|
||||
0x65, 0x22, 0x4e, 0x0a, 0x12, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x67,
|
||||
0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65,
|
||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e,
|
||||
0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65,
|
||||
0x72, 0x22, 0xca, 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65, 0x64, 0x46, 0x69,
|
||||
0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6e,
|
||||
0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e,
|
||||
0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69,
|
||||
0x63, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x10,
|
||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74,
|
||||
0x12, 0x4c, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72,
|
||||
0x70, 0x72, 0x69, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65,
|
||||
0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c,
|
||||
0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x52, 0x11, 0x72, 0x65, 0x6d,
|
||||
0x6f, 0x74, 0x65, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74,
|
||||
}
|
||||
|
||||
var (
|
||||
file_serialize_FingerprintProtocol_proto_rawDescOnce sync.Once
|
||||
file_serialize_FingerprintProtocol_proto_rawDescData = file_serialize_FingerprintProtocol_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_serialize_FingerprintProtocol_proto_rawDescGZIP() []byte {
|
||||
file_serialize_FingerprintProtocol_proto_rawDescOnce.Do(func() {
|
||||
file_serialize_FingerprintProtocol_proto_rawDescData = protoimpl.X.CompressGZIP(file_serialize_FingerprintProtocol_proto_rawDescData)
|
||||
})
|
||||
return file_serialize_FingerprintProtocol_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_serialize_FingerprintProtocol_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_serialize_FingerprintProtocol_proto_goTypes = []interface{}{
|
||||
(*LogicalFingerprint)(nil), // 0: textsecure.LogicalFingerprint
|
||||
(*CombinedFingerprints)(nil), // 1: textsecure.CombinedFingerprints
|
||||
}
|
||||
var file_serialize_FingerprintProtocol_proto_depIdxs = []int32{
|
||||
0, // 0: textsecure.CombinedFingerprints.localFingerprint:type_name -> textsecure.LogicalFingerprint
|
||||
0, // 1: textsecure.CombinedFingerprints.remoteFingerprint:type_name -> textsecure.LogicalFingerprint
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_serialize_FingerprintProtocol_proto_init() }
|
||||
func file_serialize_FingerprintProtocol_proto_init() {
|
||||
if File_serialize_FingerprintProtocol_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_serialize_FingerprintProtocol_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*LogicalFingerprint); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_FingerprintProtocol_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*CombinedFingerprints); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_serialize_FingerprintProtocol_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_serialize_FingerprintProtocol_proto_goTypes,
|
||||
DependencyIndexes: file_serialize_FingerprintProtocol_proto_depIdxs,
|
||||
MessageInfos: file_serialize_FingerprintProtocol_proto_msgTypes,
|
||||
}.Build()
|
||||
File_serialize_FingerprintProtocol_proto = out.File
|
||||
file_serialize_FingerprintProtocol_proto_rawDesc = nil
|
||||
file_serialize_FingerprintProtocol_proto_goTypes = nil
|
||||
file_serialize_FingerprintProtocol_proto_depIdxs = nil
|
||||
}
|
14
vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto
vendored
Normal file
14
vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/FingerprintProtocol.proto
|
||||
syntax = "proto2";
|
||||
package textsecure;
|
||||
|
||||
message LogicalFingerprint {
|
||||
optional bytes content = 1;
|
||||
optional bytes identifier = 2; // Version 0
|
||||
}
|
||||
|
||||
message CombinedFingerprints {
|
||||
optional uint32 version = 1;
|
||||
optional LogicalFingerprint localFingerprint = 2;
|
||||
optional LogicalFingerprint remoteFingerprint = 3;
|
||||
}
|
303
vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go
vendored
Normal file
303
vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
package serialize
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
groupRecord "go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// NewJSONSerializer will return a serializer for all Signal objects that will
|
||||
// be responsible for converting objects to and from JSON bytes.
|
||||
func NewJSONSerializer() *Serializer {
|
||||
serializer := NewSerializer()
|
||||
|
||||
serializer.SignalMessage = &JSONSignalMessageSerializer{}
|
||||
serializer.PreKeySignalMessage = &JSONPreKeySignalMessageSerializer{}
|
||||
serializer.SignedPreKeyRecord = &JSONSignedPreKeyRecordSerializer{}
|
||||
serializer.PreKeyRecord = &JSONPreKeyRecordSerializer{}
|
||||
serializer.State = &JSONStateSerializer{}
|
||||
serializer.Session = &JSONSessionSerializer{}
|
||||
serializer.SenderKeyMessage = &JSONSenderKeyMessageSerializer{}
|
||||
serializer.SenderKeyDistributionMessage = &JSONSenderKeyDistributionMessageSerializer{}
|
||||
serializer.SenderKeyRecord = &JSONSenderKeySessionSerializer{}
|
||||
serializer.SenderKeyState = &JSONSenderKeyStateSerializer{}
|
||||
|
||||
return serializer
|
||||
}
|
||||
|
||||
// JSONSignalMessageSerializer is a structure for serializing signal messages into
|
||||
// and from JSON.
|
||||
type JSONSignalMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a signal message structure and convert it to JSON bytes.
|
||||
func (j *JSONSignalMessageSerializer) Serialize(signalMessage *protocol.SignalMessageStructure) []byte {
|
||||
serialized, err := json.Marshal(*signalMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing signal message: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a signal message structure.
|
||||
func (j *JSONSignalMessageSerializer) Deserialize(serialized []byte) (*protocol.SignalMessageStructure, error) {
|
||||
var signalMessage protocol.SignalMessageStructure
|
||||
err := json.Unmarshal(serialized, &signalMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &signalMessage, nil
|
||||
}
|
||||
|
||||
// JSONPreKeySignalMessageSerializer is a structure for serializing prekey signal messages
|
||||
// into and from JSON.
|
||||
type JSONPreKeySignalMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a prekey signal message structure and convert it to JSON bytes.
|
||||
func (j *JSONPreKeySignalMessageSerializer) Serialize(signalMessage *protocol.PreKeySignalMessageStructure) []byte {
|
||||
serialized, err := json.Marshal(signalMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing prekey signal message: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a prekey signal message structure.
|
||||
func (j *JSONPreKeySignalMessageSerializer) Deserialize(serialized []byte) (*protocol.PreKeySignalMessageStructure, error) {
|
||||
var preKeySignalMessage protocol.PreKeySignalMessageStructure
|
||||
err := json.Unmarshal(serialized, &preKeySignalMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing prekey signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &preKeySignalMessage, nil
|
||||
}
|
||||
|
||||
// JSONSignedPreKeyRecordSerializer is a structure for serializing signed prekey records
|
||||
// into and from JSON.
|
||||
type JSONSignedPreKeyRecordSerializer struct{}
|
||||
|
||||
// Serialize will take a signed prekey record structure and convert it to JSON bytes.
|
||||
func (j *JSONSignedPreKeyRecordSerializer) Serialize(signedPreKey *record.SignedPreKeyStructure) []byte {
|
||||
serialized, err := json.Marshal(signedPreKey)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing signed prekey record: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a signed prekey record structure.
|
||||
func (j *JSONSignedPreKeyRecordSerializer) Deserialize(serialized []byte) (*record.SignedPreKeyStructure, error) {
|
||||
var signedPreKeyStructure record.SignedPreKeyStructure
|
||||
err := json.Unmarshal(serialized, &signedPreKeyStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing signed prekey record: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &signedPreKeyStructure, nil
|
||||
}
|
||||
|
||||
// JSONPreKeyRecordSerializer is a structure for serializing prekey records
|
||||
// into and from JSON.
|
||||
type JSONPreKeyRecordSerializer struct{}
|
||||
|
||||
// Serialize will take a prekey record structure and convert it to JSON bytes.
|
||||
func (j *JSONPreKeyRecordSerializer) Serialize(preKey *record.PreKeyStructure) []byte {
|
||||
serialized, err := json.Marshal(preKey)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing prekey record: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a prekey record structure.
|
||||
func (j *JSONPreKeyRecordSerializer) Deserialize(serialized []byte) (*record.PreKeyStructure, error) {
|
||||
var preKeyStructure record.PreKeyStructure
|
||||
err := json.Unmarshal(serialized, &preKeyStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing prekey record: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &preKeyStructure, nil
|
||||
}
|
||||
|
||||
// JSONStateSerializer is a structure for serializing session states into
|
||||
// and from JSON.
|
||||
type JSONStateSerializer struct{}
|
||||
|
||||
// Serialize will take a session state structure and convert it to JSON bytes.
|
||||
func (j *JSONStateSerializer) Serialize(state *record.StateStructure) []byte {
|
||||
serialized, err := json.Marshal(state)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing session state: ", err)
|
||||
}
|
||||
logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a session state structure.
|
||||
func (j *JSONStateSerializer) Deserialize(serialized []byte) (*record.StateStructure, error) {
|
||||
var stateStructure record.StateStructure
|
||||
err := json.Unmarshal(serialized, &stateStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing session state: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &stateStructure, nil
|
||||
}
|
||||
|
||||
// JSONSessionSerializer is a structure for serializing session records into
|
||||
// and from JSON.
|
||||
type JSONSessionSerializer struct{}
|
||||
|
||||
// Serialize will take a session structure and convert it to JSON bytes.
|
||||
func (j *JSONSessionSerializer) Serialize(session *record.SessionStructure) []byte {
|
||||
serialized, err := json.Marshal(session)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing session: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a session structure, which can be
|
||||
// used to create a new Session Record object.
|
||||
func (j *JSONSessionSerializer) Deserialize(serialized []byte) (*record.SessionStructure, error) {
|
||||
var sessionStructure record.SessionStructure
|
||||
err := json.Unmarshal(serialized, &sessionStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing session: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sessionStructure, nil
|
||||
}
|
||||
|
||||
// JSONSenderKeyDistributionMessageSerializer is a structure for serializing senderkey
|
||||
// distribution records to and from JSON.
|
||||
type JSONSenderKeyDistributionMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a senderkey distribution message and convert it to JSON bytes.
|
||||
func (j *JSONSenderKeyDistributionMessageSerializer) Serialize(message *protocol.SenderKeyDistributionMessageStructure) []byte {
|
||||
serialized, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing senderkey distribution message: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a message structure, which can be
|
||||
// used to create a new SenderKey Distribution object.
|
||||
func (j *JSONSenderKeyDistributionMessageSerializer) Deserialize(serialized []byte) (*protocol.SenderKeyDistributionMessageStructure, error) {
|
||||
var msgStructure protocol.SenderKeyDistributionMessageStructure
|
||||
err := json.Unmarshal(serialized, &msgStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing senderkey distribution message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msgStructure, nil
|
||||
}
|
||||
|
||||
// JSONSenderKeyMessageSerializer is a structure for serializing senderkey
|
||||
// messages to and from JSON.
|
||||
type JSONSenderKeyMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a senderkey message and convert it to JSON bytes.
|
||||
func (j *JSONSenderKeyMessageSerializer) Serialize(message *protocol.SenderKeyMessageStructure) []byte {
|
||||
serialized, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing senderkey distribution message: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a message structure, which can be
|
||||
// used to create a new SenderKey message object.
|
||||
func (j *JSONSenderKeyMessageSerializer) Deserialize(serialized []byte) (*protocol.SenderKeyMessageStructure, error) {
|
||||
var msgStructure protocol.SenderKeyMessageStructure
|
||||
err := json.Unmarshal(serialized, &msgStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing senderkey message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msgStructure, nil
|
||||
}
|
||||
|
||||
// JSONSenderKeyStateSerializer is a structure for serializing group session states into
|
||||
// and from JSON.
|
||||
type JSONSenderKeyStateSerializer struct{}
|
||||
|
||||
// Serialize will take a session state structure and convert it to JSON bytes.
|
||||
func (j *JSONSenderKeyStateSerializer) Serialize(state *groupRecord.SenderKeyStateStructure) []byte {
|
||||
serialized, err := json.Marshal(state)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing session state: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a session state structure.
|
||||
func (j *JSONSenderKeyStateSerializer) Deserialize(serialized []byte) (*groupRecord.SenderKeyStateStructure, error) {
|
||||
var stateStructure groupRecord.SenderKeyStateStructure
|
||||
err := json.Unmarshal(serialized, &stateStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing session state: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &stateStructure, nil
|
||||
}
|
||||
|
||||
// JSONSenderKeySessionSerializer is a structure for serializing session records into
|
||||
// and from JSON.
|
||||
type JSONSenderKeySessionSerializer struct{}
|
||||
|
||||
// Serialize will take a session structure and convert it to JSON bytes.
|
||||
func (j *JSONSenderKeySessionSerializer) Serialize(session *groupRecord.SenderKeyStructure) []byte {
|
||||
serialized, err := json.Marshal(session)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing session: ", err)
|
||||
}
|
||||
// logger.Debug("Serialize result: ", string(serialized))
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in JSON bytes and return a session structure, which can be
|
||||
// used to create a new Session Record object.
|
||||
func (j *JSONSenderKeySessionSerializer) Deserialize(serialized []byte) (*groupRecord.SenderKeyStructure, error) {
|
||||
var sessionStructure groupRecord.SenderKeyStructure
|
||||
err := json.Unmarshal(serialized, &sessionStructure)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing session: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &sessionStructure, nil
|
||||
}
|
1500
vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go
vendored
Normal file
1500
vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go
vendored
Normal file
File diff suppressed because it is too large
Load Diff
114
vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto
vendored
Normal file
114
vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/LocalStorageProtocol.proto
|
||||
syntax = "proto2";
|
||||
package textsecure;
|
||||
|
||||
option java_package = "org.whispersystems.libsignal.state";
|
||||
option java_outer_classname = "StorageProtos";
|
||||
|
||||
message SessionStructure {
|
||||
message Chain {
|
||||
optional bytes senderRatchetKey = 1;
|
||||
optional bytes senderRatchetKeyPrivate = 2;
|
||||
|
||||
message ChainKey {
|
||||
optional uint32 index = 1;
|
||||
optional bytes key = 2;
|
||||
}
|
||||
|
||||
optional ChainKey chainKey = 3;
|
||||
|
||||
message MessageKey {
|
||||
optional uint32 index = 1;
|
||||
optional bytes cipherKey = 2;
|
||||
optional bytes macKey = 3;
|
||||
optional bytes iv = 4;
|
||||
}
|
||||
|
||||
repeated MessageKey messageKeys = 4;
|
||||
}
|
||||
|
||||
message PendingKeyExchange {
|
||||
optional uint32 sequence = 1;
|
||||
optional bytes localBaseKey = 2;
|
||||
optional bytes localBaseKeyPrivate = 3;
|
||||
optional bytes localRatchetKey = 4;
|
||||
optional bytes localRatchetKeyPrivate = 5;
|
||||
optional bytes localIdentityKey = 7;
|
||||
optional bytes localIdentityKeyPrivate = 8;
|
||||
}
|
||||
|
||||
message PendingPreKey {
|
||||
optional uint32 preKeyId = 1;
|
||||
optional int32 signedPreKeyId = 3;
|
||||
optional bytes baseKey = 2;
|
||||
}
|
||||
|
||||
optional uint32 sessionVersion = 1;
|
||||
optional bytes localIdentityPublic = 2;
|
||||
optional bytes remoteIdentityPublic = 3;
|
||||
|
||||
optional bytes rootKey = 4;
|
||||
optional uint32 previousCounter = 5;
|
||||
|
||||
optional Chain senderChain = 6;
|
||||
repeated Chain receiverChains = 7;
|
||||
|
||||
optional PendingKeyExchange pendingKeyExchange = 8;
|
||||
optional PendingPreKey pendingPreKey = 9;
|
||||
|
||||
optional uint32 remoteRegistrationId = 10;
|
||||
optional uint32 localRegistrationId = 11;
|
||||
|
||||
optional bool needsRefresh = 12;
|
||||
optional bytes aliceBaseKey = 13;
|
||||
}
|
||||
|
||||
message RecordStructure {
|
||||
optional SessionStructure currentSession = 1;
|
||||
repeated SessionStructure previousSessions = 2;
|
||||
}
|
||||
|
||||
message PreKeyRecordStructure {
|
||||
optional uint32 id = 1;
|
||||
optional bytes publicKey = 2;
|
||||
optional bytes privateKey = 3;
|
||||
}
|
||||
|
||||
message SignedPreKeyRecordStructure {
|
||||
optional uint32 id = 1;
|
||||
optional bytes publicKey = 2;
|
||||
optional bytes privateKey = 3;
|
||||
optional bytes signature = 4;
|
||||
optional fixed64 timestamp = 5;
|
||||
}
|
||||
|
||||
message IdentityKeyPairStructure {
|
||||
optional bytes publicKey = 1;
|
||||
optional bytes privateKey = 2;
|
||||
}
|
||||
|
||||
message SenderKeyStateStructure {
|
||||
message SenderChainKey {
|
||||
optional uint32 iteration = 1;
|
||||
optional bytes seed = 2;
|
||||
}
|
||||
|
||||
message SenderMessageKey {
|
||||
optional uint32 iteration = 1;
|
||||
optional bytes seed = 2;
|
||||
}
|
||||
|
||||
message SenderSigningKey {
|
||||
optional bytes public = 1;
|
||||
optional bytes private = 2;
|
||||
}
|
||||
|
||||
optional uint32 senderKeyId = 1;
|
||||
optional SenderChainKey senderChainKey = 2;
|
||||
optional SenderSigningKey senderSigningKey = 3;
|
||||
repeated SenderMessageKey senderMessageKeys = 4;
|
||||
}
|
||||
|
||||
message SenderKeyRecordStructure {
|
||||
repeated SenderKeyStateStructure senderKeyStates = 1;
|
||||
}
|
262
vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go
vendored
Normal file
262
vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
package serialize
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// NewProtoBufSerializer will return a serializer for all Signal objects that will
|
||||
// be responsible for converting objects to and from ProtoBuf bytes.
|
||||
func NewProtoBufSerializer() *Serializer {
|
||||
serializer := NewSerializer()
|
||||
|
||||
serializer.SignalMessage = &ProtoBufSignalMessageSerializer{}
|
||||
serializer.PreKeySignalMessage = &ProtoBufPreKeySignalMessageSerializer{}
|
||||
serializer.SenderKeyMessage = &ProtoBufSenderKeyMessageSerializer{}
|
||||
serializer.SenderKeyDistributionMessage = &ProtoBufSenderKeyDistributionMessageSerializer{}
|
||||
serializer.SignedPreKeyRecord = &JSONSignedPreKeyRecordSerializer{}
|
||||
serializer.PreKeyRecord = &JSONPreKeyRecordSerializer{}
|
||||
serializer.State = &JSONStateSerializer{}
|
||||
serializer.Session = &JSONSessionSerializer{}
|
||||
serializer.SenderKeyRecord = &JSONSenderKeySessionSerializer{}
|
||||
serializer.SenderKeyState = &JSONSenderKeyStateSerializer{}
|
||||
|
||||
return serializer
|
||||
}
|
||||
|
||||
func highBitsToInt(value byte) int {
|
||||
return int((value & 0xFF) >> 4)
|
||||
}
|
||||
|
||||
func intsToByteHighAndLow(highValue, lowValue int) byte {
|
||||
return byte((highValue<<4 | lowValue) & 0xFF)
|
||||
}
|
||||
|
||||
// ProtoBufSignalMessageSerializer is a structure for serializing signal messages into
|
||||
// and from ProtoBuf.
|
||||
type ProtoBufSignalMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a signal message structure and convert it to ProtoBuf bytes.
|
||||
func (j *ProtoBufSignalMessageSerializer) Serialize(signalMessage *protocol.SignalMessageStructure) []byte {
|
||||
sm := &SignalMessage{
|
||||
RatchetKey: signalMessage.RatchetKey,
|
||||
Counter: &signalMessage.Counter,
|
||||
PreviousCounter: &signalMessage.PreviousCounter,
|
||||
Ciphertext: signalMessage.CipherText,
|
||||
}
|
||||
var serialized []byte
|
||||
message, err := proto.Marshal(sm)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing signal message: ", err)
|
||||
}
|
||||
|
||||
if signalMessage.Version != 0 {
|
||||
serialized = append(serialized, []byte(strconv.Itoa(signalMessage.Version))...)
|
||||
}
|
||||
serialized = append(serialized, message...)
|
||||
|
||||
if signalMessage.Mac != nil {
|
||||
serialized = append(serialized, signalMessage.Mac...)
|
||||
}
|
||||
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in ProtoBuf bytes and return a signal message structure.
|
||||
func (j *ProtoBufSignalMessageSerializer) Deserialize(serialized []byte) (*protocol.SignalMessageStructure, error) {
|
||||
parts, err := bytehelper.SplitThree(serialized, 1, len(serialized)-1-protocol.MacLength, protocol.MacLength)
|
||||
if err != nil {
|
||||
logger.Error("Error split signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
version := highBitsToInt(parts[0][0])
|
||||
message := parts[1]
|
||||
mac := parts[2]
|
||||
|
||||
var sm SignalMessage
|
||||
err = proto.Unmarshal(message, &sm)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signalMessage := protocol.SignalMessageStructure{
|
||||
Version: version,
|
||||
RatchetKey: sm.GetRatchetKey(),
|
||||
Counter: sm.GetCounter(),
|
||||
PreviousCounter: sm.GetPreviousCounter(),
|
||||
CipherText: sm.GetCiphertext(),
|
||||
Mac: mac,
|
||||
}
|
||||
|
||||
return &signalMessage, nil
|
||||
}
|
||||
|
||||
// ProtoBufPreKeySignalMessageSerializer is a structure for serializing prekey signal messages
|
||||
// into and from ProtoBuf.
|
||||
type ProtoBufPreKeySignalMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a prekey signal message structure and convert it to ProtoBuf bytes.
|
||||
func (j *ProtoBufPreKeySignalMessageSerializer) Serialize(signalMessage *protocol.PreKeySignalMessageStructure) []byte {
|
||||
preKeyMessage := &PreKeySignalMessage{
|
||||
RegistrationId: &signalMessage.RegistrationID,
|
||||
SignedPreKeyId: &signalMessage.SignedPreKeyID,
|
||||
BaseKey: signalMessage.BaseKey,
|
||||
IdentityKey: signalMessage.IdentityKey,
|
||||
Message: signalMessage.Message,
|
||||
}
|
||||
|
||||
if !signalMessage.PreKeyID.IsEmpty {
|
||||
preKeyMessage.PreKeyId = &signalMessage.PreKeyID.Value
|
||||
}
|
||||
|
||||
message, err := proto.Marshal(preKeyMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing prekey signal message: ", err)
|
||||
}
|
||||
|
||||
serialized := append([]byte(strconv.Itoa(signalMessage.Version)), message...)
|
||||
logger.Debug("Serialize PreKeySignalMessage result: ", serialized)
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in ProtoBuf bytes and return a prekey signal message structure.
|
||||
func (j *ProtoBufPreKeySignalMessageSerializer) Deserialize(serialized []byte) (*protocol.PreKeySignalMessageStructure, error) {
|
||||
version := highBitsToInt(serialized[0])
|
||||
message := serialized[1:]
|
||||
var sm PreKeySignalMessage
|
||||
err := proto.Unmarshal(message, &sm)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing prekey signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
preKeyId := optional.NewEmptyUint32()
|
||||
if sm.GetPreKeyId() != 0 {
|
||||
preKeyId = optional.NewOptionalUint32(sm.GetPreKeyId())
|
||||
}
|
||||
|
||||
preKeySignalMessage := protocol.PreKeySignalMessageStructure{
|
||||
Version: version,
|
||||
RegistrationID: sm.GetRegistrationId(),
|
||||
BaseKey: sm.GetBaseKey(),
|
||||
IdentityKey: sm.GetIdentityKey(),
|
||||
SignedPreKeyID: sm.GetSignedPreKeyId(),
|
||||
Message: sm.GetMessage(),
|
||||
PreKeyID: preKeyId,
|
||||
}
|
||||
|
||||
return &preKeySignalMessage, nil
|
||||
}
|
||||
|
||||
// ProtoBufSenderKeyDistributionMessageSerializer is a structure for serializing senderkey
|
||||
// distribution records to and from ProtoBuf.
|
||||
type ProtoBufSenderKeyDistributionMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a senderkey distribution message and convert it to ProtoBuf bytes.
|
||||
func (j *ProtoBufSenderKeyDistributionMessageSerializer) Serialize(message *protocol.SenderKeyDistributionMessageStructure) []byte {
|
||||
senderDis := SenderKeyDistributionMessage{
|
||||
Id: &message.ID,
|
||||
Iteration: &message.Iteration,
|
||||
ChainKey: message.ChainKey,
|
||||
SigningKey: message.SigningKey,
|
||||
}
|
||||
|
||||
serialized, err := proto.Marshal(&senderDis)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing senderkey distribution message: ", err)
|
||||
}
|
||||
|
||||
version := strconv.Itoa(int(message.Version))
|
||||
serialized = append([]byte(version), serialized...)
|
||||
logger.Debug("Serialize result: ", serialized)
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in ProtoBuf bytes and return a message structure, which can be
|
||||
// used to create a new SenderKey Distribution object.
|
||||
func (j *ProtoBufSenderKeyDistributionMessageSerializer) Deserialize(serialized []byte) (*protocol.SenderKeyDistributionMessageStructure, error) {
|
||||
version := uint32(highBitsToInt(serialized[0]))
|
||||
message := serialized[1:]
|
||||
|
||||
var senderKeyDis SenderKeyDistributionMessage
|
||||
err := proto.Unmarshal(message, &senderKeyDis)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing senderkey distribution message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgStructure := protocol.SenderKeyDistributionMessageStructure{
|
||||
ID: senderKeyDis.GetId(),
|
||||
Iteration: senderKeyDis.GetIteration(),
|
||||
ChainKey: senderKeyDis.GetChainKey(),
|
||||
SigningKey: senderKeyDis.GetSigningKey(),
|
||||
Version: version,
|
||||
}
|
||||
return &msgStructure, nil
|
||||
}
|
||||
|
||||
// ProtoBufSenderKeyMessageSerializer is a structure for serializing senderkey
|
||||
// messages to and from ProtoBuf.
|
||||
type ProtoBufSenderKeyMessageSerializer struct{}
|
||||
|
||||
// Serialize will take a senderkey message and convert it to ProtoBuf bytes.
|
||||
func (j *ProtoBufSenderKeyMessageSerializer) Serialize(message *protocol.SenderKeyMessageStructure) []byte {
|
||||
senderMessage := &SenderKeyMessage{
|
||||
Id: &message.ID,
|
||||
Iteration: &message.Iteration,
|
||||
Ciphertext: message.CipherText,
|
||||
}
|
||||
|
||||
var serialized []byte
|
||||
m, err := proto.Marshal(senderMessage)
|
||||
if err != nil {
|
||||
logger.Error("Error serializing signal message: ", err)
|
||||
}
|
||||
|
||||
if message.Version != 0 {
|
||||
serialized = append([]byte(fmt.Sprint(message.Version)), m...)
|
||||
}
|
||||
|
||||
if message.Signature != nil {
|
||||
serialized = append(serialized, message.Signature...)
|
||||
}
|
||||
logger.Debug("Serialize result: ", serialized)
|
||||
return serialized
|
||||
}
|
||||
|
||||
// Deserialize will take in ProtoBuf bytes and return a message structure, which can be
|
||||
// used to create a new SenderKey message object.
|
||||
func (j *ProtoBufSenderKeyMessageSerializer) Deserialize(serialized []byte) (*protocol.SenderKeyMessageStructure, error) {
|
||||
parts, err := bytehelper.SplitThree(serialized, 1, len(serialized)-1-64, 64)
|
||||
if err != nil {
|
||||
logger.Error("Error split signal message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
version := uint32(highBitsToInt(parts[0][0]))
|
||||
message := parts[1]
|
||||
signature := parts[2]
|
||||
|
||||
var senderKey SenderKeyMessage
|
||||
err = proto.Unmarshal(message, &senderKey)
|
||||
if err != nil {
|
||||
logger.Error("Error deserializing senderkey message: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgStructure := protocol.SenderKeyMessageStructure{
|
||||
Version: version,
|
||||
ID: senderKey.GetId(),
|
||||
Iteration: senderKey.GetIteration(),
|
||||
CipherText: senderKey.GetCiphertext(),
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
return &msgStructure, nil
|
||||
}
|
31
vendor/go.mau.fi/libsignal/serialize/Serializer.go
vendored
Normal file
31
vendor/go.mau.fi/libsignal/serialize/Serializer.go
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
// Package serialize provides a serialization structure to serialize and
|
||||
// deserialize Signal objects into storeable and transportable bytes.
|
||||
package serialize
|
||||
|
||||
import (
|
||||
groupRecord "go.mau.fi/libsignal/groups/state/record"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// NewSerializer will return a new serializer object that will be used
|
||||
// to encode/decode Signal objects into bytes.
|
||||
func NewSerializer() *Serializer {
|
||||
return &Serializer{}
|
||||
}
|
||||
|
||||
// Serializer is a structure to serialize Signal objects
|
||||
// into bytes. This allows you to use any serialization format
|
||||
// to store or send Signal objects.
|
||||
type Serializer struct {
|
||||
SenderKeyRecord groupRecord.SenderKeySerializer
|
||||
SenderKeyState groupRecord.SenderKeyStateSerializer
|
||||
SignalMessage protocol.SignalMessageSerializer
|
||||
PreKeySignalMessage protocol.PreKeySignalMessageSerializer
|
||||
SenderKeyMessage protocol.SenderKeyMessageSerializer
|
||||
SenderKeyDistributionMessage protocol.SenderKeyDistributionMessageSerializer
|
||||
SignedPreKeyRecord record.SignedPreKeySerializer
|
||||
PreKeyRecord record.PreKeySerializer
|
||||
State record.StateSerializer
|
||||
Session record.SessionSerializer
|
||||
}
|
640
vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go
vendored
Normal file
640
vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go
vendored
Normal file
@ -0,0 +1,640 @@
|
||||
// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/WhisperTextProtocol.proto
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.4
|
||||
// source: serialize/WhisperTextProtocol.proto
|
||||
|
||||
package serialize
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type SignalMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RatchetKey []byte `protobuf:"bytes,1,opt,name=ratchetKey" json:"ratchetKey,omitempty"`
|
||||
Counter *uint32 `protobuf:"varint,2,opt,name=counter" json:"counter,omitempty"`
|
||||
PreviousCounter *uint32 `protobuf:"varint,3,opt,name=previousCounter" json:"previousCounter,omitempty"`
|
||||
Ciphertext []byte `protobuf:"bytes,4,opt,name=ciphertext" json:"ciphertext,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SignalMessage) Reset() {
|
||||
*x = SignalMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SignalMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SignalMessage) ProtoMessage() {}
|
||||
|
||||
func (x *SignalMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SignalMessage.ProtoReflect.Descriptor instead.
|
||||
func (*SignalMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *SignalMessage) GetRatchetKey() []byte {
|
||||
if x != nil {
|
||||
return x.RatchetKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SignalMessage) GetCounter() uint32 {
|
||||
if x != nil && x.Counter != nil {
|
||||
return *x.Counter
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SignalMessage) GetPreviousCounter() uint32 {
|
||||
if x != nil && x.PreviousCounter != nil {
|
||||
return *x.PreviousCounter
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SignalMessage) GetCiphertext() []byte {
|
||||
if x != nil {
|
||||
return x.Ciphertext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PreKeySignalMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RegistrationId *uint32 `protobuf:"varint,5,opt,name=registrationId" json:"registrationId,omitempty"`
|
||||
PreKeyId *uint32 `protobuf:"varint,1,opt,name=preKeyId" json:"preKeyId,omitempty"`
|
||||
SignedPreKeyId *uint32 `protobuf:"varint,6,opt,name=signedPreKeyId" json:"signedPreKeyId,omitempty"`
|
||||
BaseKey []byte `protobuf:"bytes,2,opt,name=baseKey" json:"baseKey,omitempty"`
|
||||
IdentityKey []byte `protobuf:"bytes,3,opt,name=identityKey" json:"identityKey,omitempty"`
|
||||
Message []byte `protobuf:"bytes,4,opt,name=message" json:"message,omitempty"` // SignalMessage
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) Reset() {
|
||||
*x = PreKeySignalMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PreKeySignalMessage) ProtoMessage() {}
|
||||
|
||||
func (x *PreKeySignalMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PreKeySignalMessage.ProtoReflect.Descriptor instead.
|
||||
func (*PreKeySignalMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetRegistrationId() uint32 {
|
||||
if x != nil && x.RegistrationId != nil {
|
||||
return *x.RegistrationId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetPreKeyId() uint32 {
|
||||
if x != nil && x.PreKeyId != nil {
|
||||
return *x.PreKeyId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetSignedPreKeyId() uint32 {
|
||||
if x != nil && x.SignedPreKeyId != nil {
|
||||
return *x.SignedPreKeyId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetBaseKey() []byte {
|
||||
if x != nil {
|
||||
return x.BaseKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetIdentityKey() []byte {
|
||||
if x != nil {
|
||||
return x.IdentityKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PreKeySignalMessage) GetMessage() []byte {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type KeyExchangeMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id *uint32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
BaseKey []byte `protobuf:"bytes,2,opt,name=baseKey" json:"baseKey,omitempty"`
|
||||
RatchetKey []byte `protobuf:"bytes,3,opt,name=ratchetKey" json:"ratchetKey,omitempty"`
|
||||
IdentityKey []byte `protobuf:"bytes,4,opt,name=identityKey" json:"identityKey,omitempty"`
|
||||
BaseKeySignature []byte `protobuf:"bytes,5,opt,name=baseKeySignature" json:"baseKeySignature,omitempty"`
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) Reset() {
|
||||
*x = KeyExchangeMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*KeyExchangeMessage) ProtoMessage() {}
|
||||
|
||||
func (x *KeyExchangeMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use KeyExchangeMessage.ProtoReflect.Descriptor instead.
|
||||
func (*KeyExchangeMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) GetId() uint32 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) GetBaseKey() []byte {
|
||||
if x != nil {
|
||||
return x.BaseKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) GetRatchetKey() []byte {
|
||||
if x != nil {
|
||||
return x.RatchetKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) GetIdentityKey() []byte {
|
||||
if x != nil {
|
||||
return x.IdentityKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *KeyExchangeMessage) GetBaseKeySignature() []byte {
|
||||
if x != nil {
|
||||
return x.BaseKeySignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SenderKeyMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id *uint32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Iteration *uint32 `protobuf:"varint,2,opt,name=iteration" json:"iteration,omitempty"`
|
||||
Ciphertext []byte `protobuf:"bytes,3,opt,name=ciphertext" json:"ciphertext,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SenderKeyMessage) Reset() {
|
||||
*x = SenderKeyMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SenderKeyMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SenderKeyMessage) ProtoMessage() {}
|
||||
|
||||
func (x *SenderKeyMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SenderKeyMessage.ProtoReflect.Descriptor instead.
|
||||
func (*SenderKeyMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *SenderKeyMessage) GetId() uint32 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SenderKeyMessage) GetIteration() uint32 {
|
||||
if x != nil && x.Iteration != nil {
|
||||
return *x.Iteration
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SenderKeyMessage) GetCiphertext() []byte {
|
||||
if x != nil {
|
||||
return x.Ciphertext
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SenderKeyDistributionMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id *uint32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
|
||||
Iteration *uint32 `protobuf:"varint,2,opt,name=iteration" json:"iteration,omitempty"`
|
||||
ChainKey []byte `protobuf:"bytes,3,opt,name=chainKey" json:"chainKey,omitempty"`
|
||||
SigningKey []byte `protobuf:"bytes,4,opt,name=signingKey" json:"signingKey,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) Reset() {
|
||||
*x = SenderKeyDistributionMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SenderKeyDistributionMessage) ProtoMessage() {}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SenderKeyDistributionMessage.ProtoReflect.Descriptor instead.
|
||||
func (*SenderKeyDistributionMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) GetId() uint32 {
|
||||
if x != nil && x.Id != nil {
|
||||
return *x.Id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) GetIteration() uint32 {
|
||||
if x != nil && x.Iteration != nil {
|
||||
return *x.Iteration
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) GetChainKey() []byte {
|
||||
if x != nil {
|
||||
return x.ChainKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SenderKeyDistributionMessage) GetSigningKey() []byte {
|
||||
if x != nil {
|
||||
return x.SigningKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DeviceConsistencyCodeMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Generation *uint32 `protobuf:"varint,1,opt,name=generation" json:"generation,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,opt,name=signature" json:"signature,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeviceConsistencyCodeMessage) Reset() {
|
||||
*x = DeviceConsistencyCodeMessage{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DeviceConsistencyCodeMessage) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DeviceConsistencyCodeMessage) ProtoMessage() {}
|
||||
|
||||
func (x *DeviceConsistencyCodeMessage) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_serialize_WhisperTextProtocol_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DeviceConsistencyCodeMessage.ProtoReflect.Descriptor instead.
|
||||
func (*DeviceConsistencyCodeMessage) Descriptor() ([]byte, []int) {
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *DeviceConsistencyCodeMessage) GetGeneration() uint32 {
|
||||
if x != nil && x.Generation != nil {
|
||||
return *x.Generation
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DeviceConsistencyCodeMessage) GetSignature() []byte {
|
||||
if x != nil {
|
||||
return x.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_serialize_WhisperTextProtocol_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_serialize_WhisperTextProtocol_proto_rawDesc = []byte{
|
||||
0x0a, 0x23, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x2f, 0x57, 0x68, 0x69, 0x73,
|
||||
0x70, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72,
|
||||
0x65, 0x22, 0x93, 0x01, 0x0a, 0x0d, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65,
|
||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74,
|
||||
0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a,
|
||||
0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73,
|
||||
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65,
|
||||
0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70,
|
||||
0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0xd7, 0x01, 0x0a, 0x13, 0x50, 0x72, 0x65, 0x4b,
|
||||
0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
|
||||
0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49,
|
||||
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x4b, 0x65,
|
||||
0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x65, 0x4b, 0x65,
|
||||
0x79, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x72, 0x65,
|
||||
0x4b, 0x65, 0x79, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x65, 0x64, 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x62,
|
||||
0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x61,
|
||||
0x73, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74,
|
||||
0x79, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x22, 0xac, 0x01, 0x0a, 0x12, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x73, 0x65,
|
||||
0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x4b,
|
||||
0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x72, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b,
|
||||
0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65,
|
||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74,
|
||||
0x79, 0x4b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x62, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x53,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10,
|
||||
0x62, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x22, 0x60, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x4d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65,
|
||||
0x78, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x1c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79,
|
||||
0x44, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73,
|
||||
0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a,
|
||||
0x0a, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x22, 0x5c, 0x0a,
|
||||
0x1c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e,
|
||||
0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a,
|
||||
0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x0d, 0x52, 0x0a, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a,
|
||||
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
}
|
||||
|
||||
var (
|
||||
file_serialize_WhisperTextProtocol_proto_rawDescOnce sync.Once
|
||||
file_serialize_WhisperTextProtocol_proto_rawDescData = file_serialize_WhisperTextProtocol_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_serialize_WhisperTextProtocol_proto_rawDescGZIP() []byte {
|
||||
file_serialize_WhisperTextProtocol_proto_rawDescOnce.Do(func() {
|
||||
file_serialize_WhisperTextProtocol_proto_rawDescData = protoimpl.X.CompressGZIP(file_serialize_WhisperTextProtocol_proto_rawDescData)
|
||||
})
|
||||
return file_serialize_WhisperTextProtocol_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_serialize_WhisperTextProtocol_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_serialize_WhisperTextProtocol_proto_goTypes = []interface{}{
|
||||
(*SignalMessage)(nil), // 0: textsecure.SignalMessage
|
||||
(*PreKeySignalMessage)(nil), // 1: textsecure.PreKeySignalMessage
|
||||
(*KeyExchangeMessage)(nil), // 2: textsecure.KeyExchangeMessage
|
||||
(*SenderKeyMessage)(nil), // 3: textsecure.SenderKeyMessage
|
||||
(*SenderKeyDistributionMessage)(nil), // 4: textsecure.SenderKeyDistributionMessage
|
||||
(*DeviceConsistencyCodeMessage)(nil), // 5: textsecure.DeviceConsistencyCodeMessage
|
||||
}
|
||||
var file_serialize_WhisperTextProtocol_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_serialize_WhisperTextProtocol_proto_init() }
|
||||
func file_serialize_WhisperTextProtocol_proto_init() {
|
||||
if File_serialize_WhisperTextProtocol_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SignalMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*PreKeySignalMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*KeyExchangeMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SenderKeyMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SenderKeyDistributionMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_serialize_WhisperTextProtocol_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DeviceConsistencyCodeMessage); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_serialize_WhisperTextProtocol_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_serialize_WhisperTextProtocol_proto_goTypes,
|
||||
DependencyIndexes: file_serialize_WhisperTextProtocol_proto_depIdxs,
|
||||
MessageInfos: file_serialize_WhisperTextProtocol_proto_msgTypes,
|
||||
}.Build()
|
||||
File_serialize_WhisperTextProtocol_proto = out.File
|
||||
file_serialize_WhisperTextProtocol_proto_rawDesc = nil
|
||||
file_serialize_WhisperTextProtocol_proto_goTypes = nil
|
||||
file_serialize_WhisperTextProtocol_proto_depIdxs = nil
|
||||
}
|
45
vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto
vendored
Normal file
45
vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/WhisperTextProtocol.proto
|
||||
syntax = "proto2";
|
||||
package textsecure;
|
||||
|
||||
message SignalMessage {
|
||||
optional bytes ratchetKey = 1;
|
||||
optional uint32 counter = 2;
|
||||
optional uint32 previousCounter = 3;
|
||||
optional bytes ciphertext = 4;
|
||||
}
|
||||
|
||||
message PreKeySignalMessage {
|
||||
optional uint32 registrationId = 5;
|
||||
optional uint32 preKeyId = 1;
|
||||
optional uint32 signedPreKeyId = 6;
|
||||
optional bytes baseKey = 2;
|
||||
optional bytes identityKey = 3;
|
||||
optional bytes message = 4; // SignalMessage
|
||||
}
|
||||
|
||||
message KeyExchangeMessage {
|
||||
optional uint32 id = 1;
|
||||
optional bytes baseKey = 2;
|
||||
optional bytes ratchetKey = 3;
|
||||
optional bytes identityKey = 4;
|
||||
optional bytes baseKeySignature = 5;
|
||||
}
|
||||
|
||||
message SenderKeyMessage {
|
||||
optional uint32 id = 1;
|
||||
optional uint32 iteration = 2;
|
||||
optional bytes ciphertext = 3;
|
||||
}
|
||||
|
||||
message SenderKeyDistributionMessage {
|
||||
optional uint32 id = 1;
|
||||
optional uint32 iteration = 2;
|
||||
optional bytes chainKey = 3;
|
||||
optional bytes signingKey = 4;
|
||||
}
|
||||
|
||||
message DeviceConsistencyCodeMessage {
|
||||
optional uint32 generation = 1;
|
||||
optional bytes signature = 2;
|
||||
}
|
272
vendor/go.mau.fi/libsignal/session/Session.go
vendored
Normal file
272
vendor/go.mau.fi/libsignal/session/Session.go
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
// Package session provides the methods necessary to build sessions
|
||||
package session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/prekey"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/ratchet"
|
||||
"go.mau.fi/libsignal/serialize"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
"go.mau.fi/libsignal/state/store"
|
||||
"go.mau.fi/libsignal/util/medium"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewBuilder constructs a session builder.
|
||||
func NewBuilder(sessionStore store.Session, preKeyStore store.PreKey,
|
||||
signedStore store.SignedPreKey, identityStore store.IdentityKey,
|
||||
remoteAddress *protocol.SignalAddress, serializer *serialize.Serializer) *Builder {
|
||||
|
||||
builder := Builder{
|
||||
sessionStore: sessionStore,
|
||||
preKeyStore: preKeyStore,
|
||||
signedPreKeyStore: signedStore,
|
||||
identityKeyStore: identityStore,
|
||||
remoteAddress: remoteAddress,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &builder
|
||||
}
|
||||
|
||||
// NewBuilderFromSignal Store constructs a session builder using a
|
||||
// SignalProtocol Store.
|
||||
func NewBuilderFromSignal(signalStore store.SignalProtocol,
|
||||
remoteAddress *protocol.SignalAddress, serializer *serialize.Serializer) *Builder {
|
||||
|
||||
builder := Builder{
|
||||
sessionStore: signalStore,
|
||||
preKeyStore: signalStore,
|
||||
signedPreKeyStore: signalStore,
|
||||
identityKeyStore: signalStore,
|
||||
remoteAddress: remoteAddress,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &builder
|
||||
}
|
||||
|
||||
// Builder is responsible for setting up encrypted sessions.
|
||||
// Once a session has been established, SessionCipher can be
|
||||
// used to encrypt/decrypt messages in that session.
|
||||
//
|
||||
// Sessions are built from one of three different vectors:
|
||||
// * PreKeyBundle retrieved from a server.
|
||||
// * PreKeySignalMessage received from a client.
|
||||
// * KeyExchangeMessage sent to or received from a client.
|
||||
//
|
||||
// Sessions are constructed per recipientId + deviceId tuple.
|
||||
// Remote logical users are identified by their recipientId,
|
||||
// and each logical recipientId can have multiple physical
|
||||
// devices.
|
||||
type Builder struct {
|
||||
sessionStore store.Session
|
||||
preKeyStore store.PreKey
|
||||
signedPreKeyStore store.SignedPreKey
|
||||
identityKeyStore store.IdentityKey
|
||||
remoteAddress *protocol.SignalAddress
|
||||
serializer *serialize.Serializer
|
||||
}
|
||||
|
||||
// Process builds a new session from a session record and pre
|
||||
// key signal message.
|
||||
func (b *Builder) Process(sessionRecord *record.Session, message *protocol.PreKeySignalMessage) (unsignedPreKeyID *optional.Uint32, err error) {
|
||||
|
||||
// Check to see if the keys are trusted.
|
||||
theirIdentityKey := message.IdentityKey()
|
||||
if !(b.identityKeyStore.IsTrustedIdentity(b.remoteAddress, theirIdentityKey)) {
|
||||
return nil, signalerror.ErrUntrustedIdentity
|
||||
}
|
||||
|
||||
// Use version 3 of the signal/axolotl protocol.
|
||||
unsignedPreKeyID, err = b.processV3(sessionRecord, message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Save the identity key to our identity store.
|
||||
b.identityKeyStore.SaveIdentity(b.remoteAddress, theirIdentityKey)
|
||||
|
||||
// Return the unsignedPreKeyID
|
||||
return unsignedPreKeyID, nil
|
||||
}
|
||||
|
||||
// ProcessV3 builds a new session from a session record and pre key
|
||||
// signal message. After a session is constructed in this way, the embedded
|
||||
// SignalMessage can be decrypted.
|
||||
func (b *Builder) processV3(sessionRecord *record.Session,
|
||||
message *protocol.PreKeySignalMessage) (unsignedPreKeyID *optional.Uint32, err error) {
|
||||
|
||||
logger.Debug("Processing message with PreKeyID: ", message.PreKeyID())
|
||||
// Check to see if we've already set up a session for this V3 message.
|
||||
sessionExists := sessionRecord.HasSessionState(
|
||||
message.MessageVersion(),
|
||||
message.BaseKey().Serialize(),
|
||||
)
|
||||
if sessionExists {
|
||||
logger.Debug("We've already setup a session for this V3 message, letting bundled message fall through...")
|
||||
return optional.NewEmptyUint32(), nil
|
||||
}
|
||||
|
||||
// Load our signed prekey from our signed prekey store.
|
||||
ourSignedPreKeyRecord := b.signedPreKeyStore.LoadSignedPreKey(message.SignedPreKeyID())
|
||||
if ourSignedPreKeyRecord == nil {
|
||||
return nil, fmt.Errorf("%w with ID %d", signalerror.ErrNoSignedPreKey, message.SignedPreKeyID())
|
||||
}
|
||||
ourSignedPreKey := ourSignedPreKeyRecord.KeyPair()
|
||||
|
||||
// Build the parameters of the session.
|
||||
parameters := ratchet.NewEmptyReceiverParameters()
|
||||
parameters.SetTheirBaseKey(message.BaseKey())
|
||||
parameters.SetTheirIdentityKey(message.IdentityKey())
|
||||
parameters.SetOurIdentityKeyPair(b.identityKeyStore.GetIdentityKeyPair())
|
||||
parameters.SetOurSignedPreKey(ourSignedPreKey)
|
||||
parameters.SetOurRatchetKey(ourSignedPreKey)
|
||||
|
||||
// Set our one time pre key with the one from our prekey store
|
||||
// if the message contains a valid pre key id
|
||||
if !message.PreKeyID().IsEmpty {
|
||||
oneTimePreKey := b.preKeyStore.LoadPreKey(message.PreKeyID().Value)
|
||||
if oneTimePreKey == nil {
|
||||
return nil, fmt.Errorf("%w with ID %d", signalerror.ErrNoOneTimeKeyFound, message.PreKeyID().Value)
|
||||
}
|
||||
parameters.SetOurOneTimePreKey(oneTimePreKey.KeyPair())
|
||||
} else {
|
||||
parameters.SetOurOneTimePreKey(nil)
|
||||
}
|
||||
|
||||
// If this is a fresh record, archive our current state.
|
||||
if !sessionRecord.IsFresh() {
|
||||
sessionRecord.ArchiveCurrentState()
|
||||
}
|
||||
|
||||
///////// Initialize our session /////////
|
||||
sessionState := sessionRecord.SessionState()
|
||||
derivedKeys, sessionErr := ratchet.CalculateReceiverSession(parameters)
|
||||
if sessionErr != nil {
|
||||
return nil, sessionErr
|
||||
}
|
||||
sessionState.SetVersion(protocol.CurrentVersion)
|
||||
sessionState.SetRemoteIdentityKey(parameters.TheirIdentityKey())
|
||||
sessionState.SetLocalIdentityKey(parameters.OurIdentityKeyPair().PublicKey())
|
||||
sessionState.SetSenderChain(parameters.OurRatchetKey(), derivedKeys.ChainKey)
|
||||
sessionState.SetRootKey(derivedKeys.RootKey)
|
||||
|
||||
// Set the session's registration ids and base key
|
||||
sessionState.SetLocalRegistrationID(b.identityKeyStore.GetLocalRegistrationId())
|
||||
sessionState.SetRemoteRegistrationID(message.RegistrationID())
|
||||
sessionState.SetSenderBaseKey(message.BaseKey().Serialize())
|
||||
|
||||
// Remove the PreKey from our store and return the message prekey id if it is valid.
|
||||
if message.PreKeyID() != nil && message.PreKeyID().Value != medium.MaxValue {
|
||||
return message.PreKeyID(), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// ProcessBundle builds a new session from a PreKeyBundle retrieved
|
||||
// from a server.
|
||||
func (b *Builder) ProcessBundle(preKey *prekey.Bundle) error {
|
||||
// Check to see if the keys are trusted.
|
||||
if !(b.identityKeyStore.IsTrustedIdentity(b.remoteAddress, preKey.IdentityKey())) {
|
||||
return signalerror.ErrUntrustedIdentity
|
||||
}
|
||||
|
||||
// Check to see if the bundle has a signed pre key.
|
||||
if preKey.SignedPreKey() == nil {
|
||||
return signalerror.ErrNoSignedPreKey
|
||||
}
|
||||
|
||||
// Verify the signature of the pre key
|
||||
preKeyPublic := preKey.IdentityKey().PublicKey()
|
||||
preKeyBytes := preKey.SignedPreKey().Serialize()
|
||||
preKeySignature := preKey.SignedPreKeySignature()
|
||||
if !ecc.VerifySignature(preKeyPublic, preKeyBytes, preKeySignature) {
|
||||
return signalerror.ErrInvalidSignature
|
||||
}
|
||||
|
||||
// Load our session and generate keys.
|
||||
sessionRecord := b.sessionStore.LoadSession(b.remoteAddress)
|
||||
ourBaseKey, err := ecc.GenerateKeyPair()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
theirSignedPreKey := preKey.SignedPreKey()
|
||||
theirOneTimePreKey := preKey.PreKey()
|
||||
theirOneTimePreKeyID := preKey.PreKeyID()
|
||||
|
||||
// Build the parameters of the session
|
||||
parameters := ratchet.NewEmptySenderParameters()
|
||||
parameters.SetOurBaseKey(ourBaseKey)
|
||||
parameters.SetOurIdentityKey(b.identityKeyStore.GetIdentityKeyPair())
|
||||
parameters.SetTheirIdentityKey(preKey.IdentityKey())
|
||||
parameters.SetTheirSignedPreKey(theirSignedPreKey)
|
||||
parameters.SetTheirRatchetKey(theirSignedPreKey)
|
||||
parameters.SetTheirOneTimePreKey(theirOneTimePreKey)
|
||||
|
||||
// If this is a fresh record, archive our current state.
|
||||
if !sessionRecord.IsFresh() {
|
||||
sessionRecord.ArchiveCurrentState()
|
||||
}
|
||||
|
||||
///////// Initialize our session /////////
|
||||
sessionState := sessionRecord.SessionState()
|
||||
derivedKeys, sessionErr := ratchet.CalculateSenderSession(parameters)
|
||||
if sessionErr != nil {
|
||||
return sessionErr
|
||||
}
|
||||
// Generate an ephemeral "ratchet" key that will be advertised to
|
||||
// the receiving user.
|
||||
sendingRatchetKey, keyErr := ecc.GenerateKeyPair()
|
||||
if keyErr != nil {
|
||||
return keyErr
|
||||
}
|
||||
sendingChain, chainErr := derivedKeys.RootKey.CreateChain(
|
||||
parameters.TheirRatchetKey(),
|
||||
sendingRatchetKey,
|
||||
)
|
||||
if chainErr != nil {
|
||||
return chainErr
|
||||
}
|
||||
|
||||
// Calculate the sender session.
|
||||
sessionState.SetVersion(protocol.CurrentVersion)
|
||||
sessionState.SetRemoteIdentityKey(parameters.TheirIdentityKey())
|
||||
sessionState.SetLocalIdentityKey(parameters.OurIdentityKey().PublicKey())
|
||||
sessionState.AddReceiverChain(parameters.TheirRatchetKey(), derivedKeys.ChainKey.Current())
|
||||
sessionState.SetSenderChain(sendingRatchetKey, sendingChain.ChainKey)
|
||||
sessionState.SetRootKey(sendingChain.RootKey)
|
||||
|
||||
// Update our session record with the unackowledged prekey message
|
||||
sessionState.SetUnacknowledgedPreKeyMessage(
|
||||
theirOneTimePreKeyID,
|
||||
preKey.SignedPreKeyID(),
|
||||
ourBaseKey.PublicKey(),
|
||||
)
|
||||
|
||||
// Set the local registration ID based on the registration id in our identity key store.
|
||||
sessionState.SetLocalRegistrationID(
|
||||
b.identityKeyStore.GetLocalRegistrationId(),
|
||||
)
|
||||
|
||||
// Set the remote registration ID based on the given prekey bundle registrationID.
|
||||
sessionState.SetRemoteRegistrationID(
|
||||
preKey.RegistrationID(),
|
||||
)
|
||||
|
||||
// Set the sender base key in our session record state.
|
||||
sessionState.SetSenderBaseKey(
|
||||
ourBaseKey.PublicKey().Serialize(),
|
||||
)
|
||||
|
||||
// Store the session in our session store and save the identity in our identity store.
|
||||
b.sessionStore.StoreSession(b.remoteAddress, sessionRecord)
|
||||
b.identityKeyStore.SaveIdentity(b.remoteAddress, preKey.IdentityKey())
|
||||
|
||||
return nil
|
||||
}
|
366
vendor/go.mau.fi/libsignal/session/SessionCipher.go
vendored
Normal file
366
vendor/go.mau.fi/libsignal/session/SessionCipher.go
vendored
Normal file
@ -0,0 +1,366 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mau.fi/libsignal/cipher"
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/signalerror"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
"go.mau.fi/libsignal/state/store"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
const maxFutureMessages = 2000
|
||||
|
||||
// NewCipher constructs a session cipher for encrypt/decrypt operations on a
|
||||
// session. In order to use the session cipher, a session must have already
|
||||
// been created and stored using session.Builder.
|
||||
func NewCipher(builder *Builder, remoteAddress *protocol.SignalAddress) *Cipher {
|
||||
cipher := &Cipher{
|
||||
sessionStore: builder.sessionStore,
|
||||
preKeyMessageSerializer: builder.serializer.PreKeySignalMessage,
|
||||
signalMessageSerializer: builder.serializer.SignalMessage,
|
||||
preKeyStore: builder.preKeyStore,
|
||||
remoteAddress: remoteAddress,
|
||||
builder: builder,
|
||||
identityKeyStore: builder.identityKeyStore,
|
||||
}
|
||||
|
||||
return cipher
|
||||
}
|
||||
|
||||
func NewCipherFromSession(remoteAddress *protocol.SignalAddress,
|
||||
sessionStore store.Session, preKeyStore store.PreKey, identityKeyStore store.IdentityKey,
|
||||
preKeyMessageSerializer protocol.PreKeySignalMessageSerializer,
|
||||
signalMessageSerializer protocol.SignalMessageSerializer) *Cipher {
|
||||
cipher := &Cipher{
|
||||
sessionStore: sessionStore,
|
||||
preKeyMessageSerializer: preKeyMessageSerializer,
|
||||
signalMessageSerializer: signalMessageSerializer,
|
||||
preKeyStore: preKeyStore,
|
||||
remoteAddress: remoteAddress,
|
||||
identityKeyStore: identityKeyStore,
|
||||
}
|
||||
|
||||
return cipher
|
||||
}
|
||||
|
||||
// Cipher is the main entry point for Signal Protocol encrypt/decrypt operations.
|
||||
// Once a session has been established with session.Builder, this can be used for
|
||||
// all encrypt/decrypt operations within that session.
|
||||
type Cipher struct {
|
||||
sessionStore store.Session
|
||||
preKeyMessageSerializer protocol.PreKeySignalMessageSerializer
|
||||
signalMessageSerializer protocol.SignalMessageSerializer
|
||||
preKeyStore store.PreKey
|
||||
remoteAddress *protocol.SignalAddress
|
||||
builder *Builder
|
||||
identityKeyStore store.IdentityKey
|
||||
}
|
||||
|
||||
// Encrypt will take the given message in bytes and return an object that follows
|
||||
// the CiphertextMessage interface.
|
||||
func (d *Cipher) Encrypt(plaintext []byte) (protocol.CiphertextMessage, error) {
|
||||
sessionRecord := d.sessionStore.LoadSession(d.remoteAddress)
|
||||
sessionState := sessionRecord.SessionState()
|
||||
chainKey := sessionState.SenderChainKey()
|
||||
messageKeys := chainKey.MessageKeys()
|
||||
senderEphemeral := sessionState.SenderRatchetKey()
|
||||
previousCounter := sessionState.PreviousCounter()
|
||||
sessionVersion := sessionState.Version()
|
||||
|
||||
ciphertextBody, err := encrypt(messageKeys, plaintext)
|
||||
logger.Debug("Got ciphertextBody: ", ciphertextBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ciphertextMessage protocol.CiphertextMessage
|
||||
ciphertextMessage, err = protocol.NewSignalMessage(
|
||||
sessionVersion,
|
||||
chainKey.Index(),
|
||||
previousCounter,
|
||||
messageKeys.MacKey(),
|
||||
senderEphemeral,
|
||||
ciphertextBody,
|
||||
sessionState.LocalIdentityKey(),
|
||||
sessionState.RemoteIdentityKey(),
|
||||
d.signalMessageSerializer,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If we haven't established a session with the recipient yet,
|
||||
// send our message as a PreKeySignalMessage.
|
||||
if sessionState.HasUnacknowledgedPreKeyMessage() {
|
||||
items, err := sessionState.UnackPreKeyMessageItems()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
localRegistrationID := sessionState.LocalRegistrationID()
|
||||
|
||||
ciphertextMessage, err = protocol.NewPreKeySignalMessage(
|
||||
sessionVersion,
|
||||
localRegistrationID,
|
||||
items.PreKeyID(),
|
||||
items.SignedPreKeyID(),
|
||||
items.BaseKey(),
|
||||
sessionState.LocalIdentityKey(),
|
||||
ciphertextMessage.(*protocol.SignalMessage),
|
||||
d.preKeyMessageSerializer,
|
||||
d.signalMessageSerializer,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
sessionState.SetSenderChainKey(chainKey.NextKey())
|
||||
if !d.identityKeyStore.IsTrustedIdentity(d.remoteAddress, sessionState.RemoteIdentityKey()) {
|
||||
// return err
|
||||
}
|
||||
d.identityKeyStore.SaveIdentity(d.remoteAddress, sessionState.RemoteIdentityKey())
|
||||
d.sessionStore.StoreSession(d.remoteAddress, sessionRecord)
|
||||
return ciphertextMessage, nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the given message using an existing session that
|
||||
// is stored in the session store.
|
||||
func (d *Cipher) Decrypt(ciphertextMessage *protocol.SignalMessage) ([]byte, error) {
|
||||
plaintext, _, err := d.DecryptAndGetKey(ciphertextMessage)
|
||||
|
||||
return plaintext, err
|
||||
}
|
||||
|
||||
// DecryptAndGetKey decrypts the given message using an existing session that
|
||||
// is stored in the session store and returns the message keys used for encryption.
|
||||
func (d *Cipher) DecryptAndGetKey(ciphertextMessage *protocol.SignalMessage) ([]byte, *message.Keys, error) {
|
||||
if !d.sessionStore.ContainsSession(d.remoteAddress) {
|
||||
return nil, nil, fmt.Errorf("%w %s", signalerror.ErrNoSessionForUser, d.remoteAddress.String())
|
||||
}
|
||||
|
||||
// Load the session record from our session store and decrypt the message.
|
||||
sessionRecord := d.sessionStore.LoadSession(d.remoteAddress)
|
||||
plaintext, messageKeys, err := d.DecryptWithRecord(sessionRecord, ciphertextMessage)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if !d.identityKeyStore.IsTrustedIdentity(d.remoteAddress, sessionRecord.SessionState().RemoteIdentityKey()) {
|
||||
// return err
|
||||
}
|
||||
d.identityKeyStore.SaveIdentity(d.remoteAddress, sessionRecord.SessionState().RemoteIdentityKey())
|
||||
|
||||
// Store the session record in our session store.
|
||||
d.sessionStore.StoreSession(d.remoteAddress, sessionRecord)
|
||||
return plaintext, messageKeys, nil
|
||||
}
|
||||
|
||||
func (d *Cipher) DecryptMessage(ciphertextMessage *protocol.PreKeySignalMessage) ([]byte, error) {
|
||||
plaintext, _, err := d.DecryptMessageReturnKey(ciphertextMessage)
|
||||
return plaintext, err
|
||||
}
|
||||
|
||||
func (d *Cipher) DecryptMessageReturnKey(ciphertextMessage *protocol.PreKeySignalMessage) ([]byte, *message.Keys, error) {
|
||||
// Load or create session record for this session.
|
||||
sessionRecord := d.sessionStore.LoadSession(d.remoteAddress)
|
||||
unsignedPreKeyID, err := d.builder.Process(sessionRecord, ciphertextMessage)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
plaintext, keys, err := d.DecryptWithRecord(sessionRecord, ciphertextMessage.WhisperMessage())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Store the session record in our session store.
|
||||
d.sessionStore.StoreSession(d.remoteAddress, sessionRecord)
|
||||
if !unsignedPreKeyID.IsEmpty {
|
||||
d.preKeyStore.RemovePreKey(unsignedPreKeyID.Value)
|
||||
}
|
||||
return plaintext, keys, nil
|
||||
}
|
||||
|
||||
// DecryptWithKey will decrypt the given message using the given symmetric key. This
|
||||
// can be used when decrypting messages at a later time if the message key was saved.
|
||||
func (d *Cipher) DecryptWithKey(ciphertextMessage *protocol.SignalMessage, key *message.Keys) ([]byte, error) {
|
||||
logger.Debug("Decrypting ciphertext body: ", ciphertextMessage.Body())
|
||||
plaintext, err := decrypt(key, ciphertextMessage.Body())
|
||||
if err != nil {
|
||||
logger.Error("Unable to get plain text from ciphertext: ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// DecryptWithRecord decrypts the given message using the given session record.
|
||||
func (d *Cipher) DecryptWithRecord(sessionRecord *record.Session, ciphertext *protocol.SignalMessage) ([]byte, *message.Keys, error) {
|
||||
logger.Debug("Decrypting ciphertext with record: ", sessionRecord)
|
||||
previousStates := sessionRecord.PreviousSessionStates()
|
||||
sessionState := sessionRecord.SessionState()
|
||||
|
||||
// Try and decrypt the message with the current session state.
|
||||
plaintext, messageKeys, err := d.DecryptWithState(sessionState, ciphertext)
|
||||
|
||||
// If we received an error using the current session state, loop
|
||||
// through all previous states.
|
||||
if err != nil {
|
||||
logger.Warning(err)
|
||||
for i, state := range previousStates {
|
||||
// Try decrypting the message with previous states
|
||||
plaintext, messageKeys, err = d.DecryptWithState(state, ciphertext)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// If successful, remove and promote the state.
|
||||
previousStates = append(previousStates[:i], previousStates[i+1:]...)
|
||||
sessionRecord.PromoteState(state)
|
||||
|
||||
return plaintext, messageKeys, nil
|
||||
}
|
||||
|
||||
return nil, nil, signalerror.ErrNoValidSessions
|
||||
}
|
||||
|
||||
// If decryption was successful, set the session state and return the plain text.
|
||||
sessionRecord.SetState(sessionState)
|
||||
|
||||
return plaintext, messageKeys, nil
|
||||
}
|
||||
|
||||
// DecryptWithState decrypts the given message with the given session state.
|
||||
func (d *Cipher) DecryptWithState(sessionState *record.State, ciphertextMessage *protocol.SignalMessage) ([]byte, *message.Keys, error) {
|
||||
logger.Debug("Decrypting ciphertext with session state: ", sessionState)
|
||||
if !sessionState.HasSenderChain() {
|
||||
logger.Error("Unable to decrypt message with state: ", signalerror.ErrUninitializedSession)
|
||||
return nil, nil, signalerror.ErrUninitializedSession
|
||||
}
|
||||
|
||||
if ciphertextMessage.MessageVersion() != sessionState.Version() {
|
||||
logger.Error("Unable to decrypt message with state: ", signalerror.ErrWrongMessageVersion)
|
||||
return nil, nil, signalerror.ErrWrongMessageVersion
|
||||
}
|
||||
|
||||
messageVersion := ciphertextMessage.MessageVersion()
|
||||
theirEphemeral := ciphertextMessage.SenderRatchetKey()
|
||||
counter := ciphertextMessage.Counter()
|
||||
chainKey, chainCreateErr := getOrCreateChainKey(sessionState, theirEphemeral)
|
||||
if chainCreateErr != nil {
|
||||
logger.Error("Unable to get or create chain key: ", chainCreateErr)
|
||||
return nil, nil, fmt.Errorf("failed to get or create chain key: %w", chainCreateErr)
|
||||
}
|
||||
|
||||
messageKeys, keysCreateErr := getOrCreateMessageKeys(sessionState, theirEphemeral, chainKey, counter)
|
||||
if keysCreateErr != nil {
|
||||
logger.Error("Unable to get or create message keys: ", keysCreateErr)
|
||||
return nil, nil, fmt.Errorf("failed to get or create message keys: %w", keysCreateErr)
|
||||
}
|
||||
|
||||
err := ciphertextMessage.VerifyMac(messageVersion, sessionState.RemoteIdentityKey(), sessionState.LocalIdentityKey(), messageKeys.MacKey())
|
||||
if err != nil {
|
||||
logger.Error("Unable to verify ciphertext mac: ", err)
|
||||
return nil, nil, fmt.Errorf("failed to verify ciphertext MAC: %w", err)
|
||||
}
|
||||
|
||||
plaintext, err := d.DecryptWithKey(ciphertextMessage, messageKeys)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
sessionState.ClearUnackPreKeyMessage()
|
||||
|
||||
return plaintext, messageKeys, nil
|
||||
}
|
||||
|
||||
func getOrCreateMessageKeys(sessionState *record.State, theirEphemeral ecc.ECPublicKeyable,
|
||||
chainKey *chain.Key, counter uint32) (*message.Keys, error) {
|
||||
|
||||
if chainKey.Index() > counter {
|
||||
if sessionState.HasMessageKeys(theirEphemeral, counter) {
|
||||
return sessionState.RemoveMessageKeys(theirEphemeral, counter), nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w (index: %d, count: %d)", signalerror.ErrOldCounter, chainKey.Index(), counter)
|
||||
}
|
||||
|
||||
if counter-chainKey.Index() > maxFutureMessages {
|
||||
return nil, signalerror.ErrTooFarIntoFuture
|
||||
}
|
||||
|
||||
for chainKey.Index() < counter {
|
||||
messageKeys := chainKey.MessageKeys()
|
||||
sessionState.SetMessageKeys(theirEphemeral, messageKeys)
|
||||
chainKey = chainKey.NextKey()
|
||||
}
|
||||
|
||||
sessionState.SetReceiverChainKey(theirEphemeral, chainKey.NextKey())
|
||||
return chainKey.MessageKeys(), nil
|
||||
}
|
||||
|
||||
// getOrCreateChainKey will either return the existing chain key or
|
||||
// create a new one with the given session state and ephemeral key.
|
||||
func getOrCreateChainKey(sessionState *record.State, theirEphemeral ecc.ECPublicKeyable) (*chain.Key, error) {
|
||||
|
||||
// If our session state already has a receiver chain, use their
|
||||
// ephemeral key in the existing chain.
|
||||
if sessionState.HasReceiverChain(theirEphemeral) {
|
||||
return sessionState.ReceiverChainKey(theirEphemeral), nil
|
||||
}
|
||||
|
||||
// If we don't have a chain key, create one with ephemeral keys.
|
||||
rootKey := sessionState.RootKey()
|
||||
ourEphemeral := sessionState.SenderRatchetKeyPair()
|
||||
receiverChain, rErr := rootKey.CreateChain(theirEphemeral, ourEphemeral)
|
||||
if rErr != nil {
|
||||
return nil, rErr
|
||||
}
|
||||
|
||||
// Generate a new ephemeral key pair.
|
||||
ourNewEphemeral, gErr := ecc.GenerateKeyPair()
|
||||
if gErr != nil {
|
||||
return nil, gErr
|
||||
}
|
||||
|
||||
// Create a new chain using our new ephemeral key.
|
||||
senderChain, cErr := receiverChain.RootKey.CreateChain(theirEphemeral, ourNewEphemeral)
|
||||
if cErr != nil {
|
||||
return nil, cErr
|
||||
}
|
||||
|
||||
// Set our session state parameters.
|
||||
sessionState.SetRootKey(senderChain.RootKey)
|
||||
sessionState.AddReceiverChain(theirEphemeral, receiverChain.ChainKey)
|
||||
previousCounter := max(sessionState.SenderChainKey().Index()-1, 0)
|
||||
sessionState.SetPreviousCounter(previousCounter)
|
||||
sessionState.SetSenderChain(ourNewEphemeral, senderChain.ChainKey)
|
||||
|
||||
return receiverChain.ChainKey.(*chain.Key), nil
|
||||
}
|
||||
|
||||
// decrypt will use the given message keys and ciphertext and return
|
||||
// the plaintext bytes.
|
||||
func decrypt(keys *message.Keys, body []byte) ([]byte, error) {
|
||||
logger.Debug("Using cipherKey: ", keys.CipherKey())
|
||||
return cipher.DecryptCbc(keys.Iv(), keys.CipherKey(), bytehelper.CopySlice(body))
|
||||
}
|
||||
|
||||
// encrypt will use the given cipher, message keys, and plaintext bytes
|
||||
// and return ciphertext bytes.
|
||||
func encrypt(messageKeys *message.Keys, plaintext []byte) ([]byte, error) {
|
||||
logger.Debug("Using cipherKey: ", messageKeys.CipherKey())
|
||||
return cipher.EncryptCbc(messageKeys.Iv(), messageKeys.CipherKey(), plaintext)
|
||||
}
|
||||
|
||||
// Max is a uint32 implementation of math.Max
|
||||
func max(x, y uint32) uint32 {
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
37
vendor/go.mau.fi/libsignal/signalerror/errors.go
vendored
Normal file
37
vendor/go.mau.fi/libsignal/signalerror/errors.go
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
package signalerror
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrNoSenderKeyStatesInRecord = errors.New("no sender key states in record")
|
||||
ErrNoSenderKeyStateForID = errors.New("no sender key state for key ID")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUntrustedIdentity = errors.New("untrusted identity")
|
||||
ErrNoSignedPreKey = errors.New("no signed prekey found in bundle")
|
||||
ErrInvalidSignature = errors.New("invalid signature on device key")
|
||||
ErrNoOneTimeKeyFound = errors.New("prekey store didn't return one-time key")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNoValidSessions = errors.New("no valid sessions")
|
||||
ErrUninitializedSession = errors.New("uninitialized session")
|
||||
ErrWrongMessageVersion = errors.New("wrong message version")
|
||||
ErrTooFarIntoFuture = errors.New("message index is over 2000 messages into the future")
|
||||
ErrOldCounter = errors.New("received message with old counter")
|
||||
ErrNoSessionForUser = errors.New("no session found for user")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrSenderKeyStateVerificationFailed = errors.New("sender key state failed verification with given public key")
|
||||
ErrNoSenderKeyForUser = errors.New("no sender key")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrOldMessageVersion = errors.New("too old message version")
|
||||
ErrUnknownMessageVersion = errors.New("unknown message version")
|
||||
ErrIncompleteMessage = errors.New("incomplete message")
|
||||
)
|
||||
|
||||
var ErrBadMAC = errors.New("mismatching MAC in signal message")
|
157
vendor/go.mau.fi/libsignal/state/record/ChainState.go
vendored
Normal file
157
vendor/go.mau.fi/libsignal/state/record/ChainState.go
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// NewReceiverChainPair will return a new ReceiverChainPair object.
|
||||
func NewReceiverChainPair(receiverChain *Chain, index int) *ReceiverChainPair {
|
||||
return &ReceiverChainPair{
|
||||
ReceiverChain: receiverChain,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
// ReceiverChainPair is a structure for a receiver chain key and index number.
|
||||
type ReceiverChainPair struct {
|
||||
ReceiverChain *Chain
|
||||
Index int
|
||||
}
|
||||
|
||||
// NewChain returns a new Chain structure for SessionState.
|
||||
func NewChain(senderRatchetKeyPair *ecc.ECKeyPair, chainKey *chain.Key,
|
||||
messageKeys []*message.Keys) *Chain {
|
||||
|
||||
return &Chain{
|
||||
senderRatchetKeyPair: senderRatchetKeyPair,
|
||||
chainKey: chainKey,
|
||||
messageKeys: messageKeys,
|
||||
}
|
||||
}
|
||||
|
||||
// NewChainFromStructure will return a new Chain with the given
|
||||
// chain structure.
|
||||
func NewChainFromStructure(structure *ChainStructure) (*Chain, error) {
|
||||
// Alias to SliceToArray
|
||||
getArray := bytehelper.SliceToArray
|
||||
|
||||
// Build the sender ratchet key from bytes.
|
||||
senderRatchetKeyPublic, err := ecc.DecodePoint(structure.SenderRatchetKeyPublic, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var senderRatchetKeyPrivate ecc.ECPrivateKeyable
|
||||
if len(structure.SenderRatchetKeyPrivate) == 32 {
|
||||
senderRatchetKeyPrivate = ecc.NewDjbECPrivateKey(getArray(structure.SenderRatchetKeyPrivate))
|
||||
}
|
||||
senderRatchetKeyPair := ecc.NewECKeyPair(senderRatchetKeyPublic, senderRatchetKeyPrivate)
|
||||
|
||||
// Build our message keys from the message key structures.
|
||||
messageKeys := make([]*message.Keys, len(structure.MessageKeys))
|
||||
for i := range structure.MessageKeys {
|
||||
messageKeys[i] = message.NewKeysFromStruct(structure.MessageKeys[i])
|
||||
}
|
||||
|
||||
// Build our new chain state.
|
||||
chainState := NewChain(
|
||||
senderRatchetKeyPair,
|
||||
chain.NewKeyFromStruct(structure.ChainKey, kdf.DeriveSecrets),
|
||||
messageKeys,
|
||||
)
|
||||
|
||||
return chainState, nil
|
||||
}
|
||||
|
||||
// ChainStructure is a serializeable structure for chain states.
|
||||
type ChainStructure struct {
|
||||
SenderRatchetKeyPublic []byte
|
||||
SenderRatchetKeyPrivate []byte
|
||||
ChainKey *chain.KeyStructure
|
||||
MessageKeys []*message.KeysStructure
|
||||
}
|
||||
|
||||
// Chain is a structure used inside the SessionState that keeps
|
||||
// track of an ongoing ratcheting chain for a session.
|
||||
type Chain struct {
|
||||
senderRatchetKeyPair *ecc.ECKeyPair
|
||||
chainKey *chain.Key
|
||||
messageKeys []*message.Keys
|
||||
}
|
||||
|
||||
// SenderRatchetKey returns the sender's EC keypair.
|
||||
func (c *Chain) SenderRatchetKey() *ecc.ECKeyPair {
|
||||
return c.senderRatchetKeyPair
|
||||
}
|
||||
|
||||
// SetSenderRatchetKey will set the chain state with the given EC
|
||||
// key pair.
|
||||
func (c *Chain) SetSenderRatchetKey(key *ecc.ECKeyPair) {
|
||||
c.senderRatchetKeyPair = key
|
||||
}
|
||||
|
||||
// ChainKey will return the chain key in the chain state.
|
||||
func (c *Chain) ChainKey() *chain.Key {
|
||||
return c.chainKey
|
||||
}
|
||||
|
||||
// SetChainKey will set the chain state's chain key.
|
||||
func (c *Chain) SetChainKey(key *chain.Key) {
|
||||
c.chainKey = key
|
||||
}
|
||||
|
||||
// MessageKeys will return the message keys associated with the
|
||||
// chain state.
|
||||
func (c *Chain) MessageKeys() []*message.Keys {
|
||||
return c.messageKeys
|
||||
}
|
||||
|
||||
// SetMessageKeys will set the chain state with the given message
|
||||
// keys.
|
||||
func (c *Chain) SetMessageKeys(keys []*message.Keys) {
|
||||
c.messageKeys = keys
|
||||
}
|
||||
|
||||
// AddMessageKeys will append the chain state with the given
|
||||
// message keys.
|
||||
func (c *Chain) AddMessageKeys(keys *message.Keys) {
|
||||
c.messageKeys = append(c.messageKeys, keys)
|
||||
}
|
||||
|
||||
// PopFirstMessageKeys will remove the first message key from
|
||||
// the chain's list of message keys.
|
||||
func (c *Chain) PopFirstMessageKeys() *message.Keys {
|
||||
removed := c.messageKeys[0]
|
||||
c.messageKeys = c.messageKeys[1:]
|
||||
|
||||
return removed
|
||||
}
|
||||
|
||||
// structure returns a serializeable structure of the chain state.
|
||||
func (c *Chain) structure() *ChainStructure {
|
||||
// Alias to ArrayToSlice
|
||||
getSlice := bytehelper.ArrayToSlice
|
||||
|
||||
// Convert our message keys into a serializeable structure.
|
||||
messageKeys := make([]*message.KeysStructure, len(c.messageKeys))
|
||||
for i := range c.messageKeys {
|
||||
messageKeys[i] = message.NewStructFromKeys(c.messageKeys[i])
|
||||
}
|
||||
|
||||
// Convert our sender ratchet key private
|
||||
var senderRatchetKeyPrivate []byte
|
||||
if c.senderRatchetKeyPair.PrivateKey() != nil {
|
||||
senderRatchetKeyPrivate = getSlice(c.senderRatchetKeyPair.PrivateKey().Serialize())
|
||||
}
|
||||
|
||||
// Build the chain structure.
|
||||
return &ChainStructure{
|
||||
SenderRatchetKeyPublic: c.senderRatchetKeyPair.PublicKey().Serialize(),
|
||||
SenderRatchetKeyPrivate: senderRatchetKeyPrivate,
|
||||
ChainKey: chain.NewStructFromKey(c.chainKey),
|
||||
MessageKeys: messageKeys,
|
||||
}
|
||||
}
|
3
vendor/go.mau.fi/libsignal/state/record/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/state/record/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package record provides the state and record of an ongoing double
|
||||
// ratchet session.
|
||||
package record
|
91
vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
vendored
Normal file
91
vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// NewPendingKeyExchange will return a new PendingKeyExchange object.
|
||||
func NewPendingKeyExchange(sequence uint32, localBaseKeyPair, localRatchetKeyPair *ecc.ECKeyPair,
|
||||
localIdentityKeyPair *identity.KeyPair) *PendingKeyExchange {
|
||||
|
||||
return &PendingKeyExchange{
|
||||
sequence: sequence,
|
||||
localBaseKeyPair: localBaseKeyPair,
|
||||
localRatchetKeyPair: localRatchetKeyPair,
|
||||
localIdentityKeyPair: localIdentityKeyPair,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPendingKeyExchangeFromStruct will return a PendingKeyExchange object from
|
||||
// the given structure. This is used to get a deserialized pending prekey exchange
|
||||
// fetched from persistent storage.
|
||||
func NewPendingKeyExchangeFromStruct(structure *PendingKeyExchangeStructure) *PendingKeyExchange {
|
||||
// Return nil if no structure was provided.
|
||||
if structure == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Alias the SliceToArray method.
|
||||
getArray := bytehelper.SliceToArray
|
||||
|
||||
// Convert the bytes in the given structure to ECC objects.
|
||||
localBaseKeyPair := ecc.NewECKeyPair(
|
||||
ecc.NewDjbECPublicKey(getArray(structure.LocalBaseKeyPublic)),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalBaseKeyPrivate)),
|
||||
)
|
||||
localRatchetKeyPair := ecc.NewECKeyPair(
|
||||
ecc.NewDjbECPublicKey(getArray(structure.LocalRatchetKeyPublic)),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalRatchetKeyPrivate)),
|
||||
)
|
||||
localIdentityKeyPair := identity.NewKeyPair(
|
||||
identity.NewKey(ecc.NewDjbECPublicKey(getArray(structure.LocalIdentityKeyPublic))),
|
||||
ecc.NewDjbECPrivateKey(getArray(structure.LocalIdentityKeyPrivate)),
|
||||
)
|
||||
|
||||
// Return the PendingKeyExchange with the deserialized keys.
|
||||
return &PendingKeyExchange{
|
||||
sequence: structure.Sequence,
|
||||
localBaseKeyPair: localBaseKeyPair,
|
||||
localRatchetKeyPair: localRatchetKeyPair,
|
||||
localIdentityKeyPair: localIdentityKeyPair,
|
||||
}
|
||||
}
|
||||
|
||||
// PendingKeyExchangeStructure is a serializable structure for pending
|
||||
// key exchanges. This structure is used for persistent storage of the
|
||||
// key exchange state.
|
||||
type PendingKeyExchangeStructure struct {
|
||||
Sequence uint32
|
||||
LocalBaseKeyPublic []byte
|
||||
LocalBaseKeyPrivate []byte
|
||||
LocalRatchetKeyPublic []byte
|
||||
LocalRatchetKeyPrivate []byte
|
||||
LocalIdentityKeyPublic []byte
|
||||
LocalIdentityKeyPrivate []byte
|
||||
}
|
||||
|
||||
// PendingKeyExchange is a structure for storing a pending
|
||||
// key exchange for a session state.
|
||||
type PendingKeyExchange struct {
|
||||
sequence uint32
|
||||
localBaseKeyPair *ecc.ECKeyPair
|
||||
localRatchetKeyPair *ecc.ECKeyPair
|
||||
localIdentityKeyPair *identity.KeyPair
|
||||
}
|
||||
|
||||
// structre will return a serializable structure of a pending key exchange
|
||||
// so it can be persistently stored.
|
||||
func (p *PendingKeyExchange) structure() *PendingKeyExchangeStructure {
|
||||
getSlice := bytehelper.ArrayToSlice
|
||||
return &PendingKeyExchangeStructure{
|
||||
Sequence: p.sequence,
|
||||
LocalBaseKeyPublic: getSlice(p.localBaseKeyPair.PublicKey().PublicKey()),
|
||||
LocalBaseKeyPrivate: getSlice(p.localBaseKeyPair.PrivateKey().Serialize()),
|
||||
LocalRatchetKeyPublic: getSlice(p.localRatchetKeyPair.PublicKey().PublicKey()),
|
||||
LocalRatchetKeyPrivate: getSlice(p.localRatchetKeyPair.PrivateKey().Serialize()),
|
||||
LocalIdentityKeyPublic: getSlice(p.localIdentityKeyPair.PublicKey().PublicKey().PublicKey()),
|
||||
LocalIdentityKeyPrivate: getSlice(p.localIdentityKeyPair.PrivateKey().Serialize()),
|
||||
}
|
||||
}
|
62
vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
vendored
Normal file
62
vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewPendingPreKey will return a new pending pre key object.
|
||||
func NewPendingPreKey(preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
baseKey ecc.ECPublicKeyable) *PendingPreKey {
|
||||
|
||||
return &PendingPreKey{
|
||||
preKeyID: preKeyID,
|
||||
signedPreKeyID: signedPreKeyID,
|
||||
baseKey: baseKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPendingPreKeyFromStruct will return a new pending prekey object from the
|
||||
// given structure.
|
||||
func NewPendingPreKeyFromStruct(preKey *PendingPreKeyStructure) (*PendingPreKey, error) {
|
||||
baseKey, err := ecc.DecodePoint(preKey.BaseKey, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pendingPreKey := NewPendingPreKey(
|
||||
preKey.PreKeyID,
|
||||
preKey.SignedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
|
||||
return pendingPreKey, nil
|
||||
}
|
||||
|
||||
// PendingPreKeyStructure is a serializeable structure for pending
|
||||
// prekeys.
|
||||
type PendingPreKeyStructure struct {
|
||||
PreKeyID *optional.Uint32
|
||||
SignedPreKeyID uint32
|
||||
BaseKey []byte
|
||||
}
|
||||
|
||||
// PendingPreKey is a structure for pending pre keys
|
||||
// for a session state.
|
||||
type PendingPreKey struct {
|
||||
preKeyID *optional.Uint32
|
||||
signedPreKeyID uint32
|
||||
baseKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// structure will return a serializeable structure of the pending prekey.
|
||||
func (p *PendingPreKey) structure() *PendingPreKeyStructure {
|
||||
if p != nil {
|
||||
return &PendingPreKeyStructure{
|
||||
PreKeyID: p.preKeyID,
|
||||
SignedPreKeyID: p.signedPreKeyID,
|
||||
BaseKey: p.baseKey.Serialize(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
90
vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
vendored
Normal file
90
vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// PreKeySerializer is an interface for serializing and deserializing
|
||||
// PreKey objects into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type PreKeySerializer interface {
|
||||
Serialize(preKey *PreKeyStructure) []byte
|
||||
Deserialize(serialized []byte) (*PreKeyStructure, error)
|
||||
}
|
||||
|
||||
// NewPreKeyFromBytes will return a prekey record from the given bytes using the given serializer.
|
||||
func NewPreKeyFromBytes(serialized []byte, serializer PreKeySerializer) (*PreKey, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
preKeyStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewPreKeyFromStruct(preKeyStructure, serializer)
|
||||
}
|
||||
|
||||
// NewPreKeyFromStruct returns a PreKey record using the given serializable structure.
|
||||
func NewPreKeyFromStruct(structure *PreKeyStructure, serializer PreKeySerializer) (*PreKey, error) {
|
||||
// Create the prekey record from the structure.
|
||||
preKey := &PreKey{
|
||||
structure: *structure,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
publicKey := ecc.NewDjbECPublicKey(bytehelper.SliceToArray(structure.PublicKey))
|
||||
privateKey := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.PrivateKey))
|
||||
keyPair := ecc.NewECKeyPair(publicKey, privateKey)
|
||||
preKey.keyPair = keyPair
|
||||
|
||||
return preKey, nil
|
||||
}
|
||||
|
||||
// NewPreKey record returns a new pre key record that can
|
||||
// be stored in a PreKeyStore.
|
||||
func NewPreKey(id uint32, keyPair *ecc.ECKeyPair, serializer PreKeySerializer) *PreKey {
|
||||
return &PreKey{
|
||||
structure: PreKeyStructure{
|
||||
ID: id,
|
||||
PublicKey: keyPair.PublicKey().Serialize(),
|
||||
PrivateKey: bytehelper.ArrayToSlice(keyPair.PrivateKey().Serialize()),
|
||||
},
|
||||
keyPair: keyPair,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// PreKeyStructure is a structure for serializing PreKey records.
|
||||
type PreKeyStructure struct {
|
||||
ID uint32
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// PreKey record is a structure for storing pre keys inside
|
||||
// a PreKeyStore.
|
||||
type PreKey struct {
|
||||
structure PreKeyStructure
|
||||
keyPair *ecc.ECKeyPair
|
||||
serializer PreKeySerializer
|
||||
}
|
||||
|
||||
// ID returns the pre key record's id.
|
||||
func (p *PreKey) ID() *optional.Uint32 {
|
||||
// TODO: manually set this to empty if empty
|
||||
return optional.NewOptionalUint32(p.structure.ID)
|
||||
}
|
||||
|
||||
// KeyPair returns the pre key record's key pair.
|
||||
func (p *PreKey) KeyPair() *ecc.ECKeyPair {
|
||||
return p.keyPair
|
||||
}
|
||||
|
||||
// Serialize uses the PreKey serializer to return the PreKey
|
||||
// as serialized bytes.
|
||||
func (p *PreKey) Serialize() []byte {
|
||||
structure := p.structure
|
||||
return p.serializer.Serialize(&structure)
|
||||
}
|
197
vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
vendored
Normal file
197
vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// archivedStatesMaxLength describes how many previous session
|
||||
// states we should keep track of.
|
||||
const archivedStatesMaxLength int = 40
|
||||
|
||||
// SessionSerializer is an interface for serializing and deserializing
|
||||
// a Signal Session into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SessionSerializer interface {
|
||||
Serialize(state *SessionStructure) []byte
|
||||
Deserialize(serialized []byte) (*SessionStructure, error)
|
||||
}
|
||||
|
||||
// NewSessionFromBytes will return a Signal Session from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSessionFromBytes(serialized []byte, serializer SessionSerializer, stateSerializer StateSerializer) (*Session, error) {
|
||||
// Use the given serializer to decode the session.
|
||||
sessionStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSessionFromStructure(sessionStructure, serializer, stateSerializer)
|
||||
}
|
||||
|
||||
// NewSession creates a new session record and uses the given session and state
|
||||
// serializers to convert the object into storeable bytes.
|
||||
func NewSession(serializer SessionSerializer, stateSerializer StateSerializer) *Session {
|
||||
record := Session{
|
||||
sessionState: NewState(stateSerializer),
|
||||
previousStates: []*State{},
|
||||
fresh: true,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &record
|
||||
}
|
||||
|
||||
// NewSessionFromStructure will return a new Signal Session from the given
|
||||
// session structure and serializer.
|
||||
func NewSessionFromStructure(structure *SessionStructure, serializer SessionSerializer,
|
||||
stateSerializer StateSerializer) (*Session, error) {
|
||||
|
||||
// Build our previous states from structure.
|
||||
previousStates := make([]*State, len(structure.PreviousStates))
|
||||
for i := range structure.PreviousStates {
|
||||
var err error
|
||||
previousStates[i], err = NewStateFromStructure(structure.PreviousStates[i], stateSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Build our current state from structure.
|
||||
sessionState, err := NewStateFromStructure(structure.SessionState, stateSerializer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build and return our session.
|
||||
session := &Session{
|
||||
previousStates: previousStates,
|
||||
sessionState: sessionState,
|
||||
serializer: serializer,
|
||||
fresh: false,
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// NewSessionFromState creates a new session record from the given
|
||||
// session state.
|
||||
func NewSessionFromState(sessionState *State, serializer SessionSerializer) *Session {
|
||||
record := Session{
|
||||
sessionState: sessionState,
|
||||
previousStates: []*State{},
|
||||
fresh: false,
|
||||
serializer: serializer,
|
||||
}
|
||||
|
||||
return &record
|
||||
}
|
||||
|
||||
// SessionStructure is a public, serializeable structure for Signal
|
||||
// Sessions. The states defined in the session are immuteable, as
|
||||
// they should not be changed by anyone but the serializer.
|
||||
type SessionStructure struct {
|
||||
SessionState *StateStructure
|
||||
PreviousStates []*StateStructure
|
||||
}
|
||||
|
||||
// Session encapsulates the state of an ongoing session.
|
||||
type Session struct {
|
||||
serializer SessionSerializer
|
||||
sessionState *State
|
||||
previousStates []*State
|
||||
fresh bool
|
||||
}
|
||||
|
||||
// SetState sets the session record's current state to the given
|
||||
// one.
|
||||
func (r *Session) SetState(sessionState *State) {
|
||||
r.sessionState = sessionState
|
||||
}
|
||||
|
||||
// IsFresh is used to determine if this is a brand new session
|
||||
// or if a session record has already existed.
|
||||
func (r *Session) IsFresh() bool {
|
||||
return r.fresh
|
||||
}
|
||||
|
||||
// SessionState returns the session state object of the current
|
||||
// session record.
|
||||
func (r *Session) SessionState() *State {
|
||||
return r.sessionState
|
||||
}
|
||||
|
||||
// PreviousSessionStates returns a list of all currently maintained
|
||||
// "previous" session states.
|
||||
func (r *Session) PreviousSessionStates() []*State {
|
||||
return r.previousStates
|
||||
}
|
||||
|
||||
// HasSessionState will check this record to see if the sender's
|
||||
// base key exists in the current and previous states.
|
||||
func (r *Session) HasSessionState(version int, senderBaseKey []byte) bool {
|
||||
// Ensure the session state version is identical to this one.
|
||||
if r.sessionState.Version() == version && (bytes.Compare(senderBaseKey, r.sessionState.SenderBaseKey()) == 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Loop through all of our previous states and see if this
|
||||
// exists in our state.
|
||||
for i := range r.previousStates {
|
||||
if r.previousStates[i].Version() == version && bytes.Compare(senderBaseKey, r.previousStates[i].SenderBaseKey()) == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// ArchiveCurrentState moves the current session state into the list
|
||||
// of "previous" session states, and replaces the current session state
|
||||
// with a fresh reset instance.
|
||||
func (r *Session) ArchiveCurrentState() {
|
||||
r.PromoteState(NewState(r.sessionState.serializer))
|
||||
}
|
||||
|
||||
// PromoteState takes the given session state and replaces it with the
|
||||
// current state, pushing the previous current state to "previousStates".
|
||||
func (r *Session) PromoteState(promotedState *State) {
|
||||
r.previousStates = r.prependStates(r.previousStates, r.sessionState)
|
||||
r.sessionState = promotedState
|
||||
|
||||
// Remove the last state if it has reached our maximum length
|
||||
if len(r.previousStates) > archivedStatesMaxLength {
|
||||
r.previousStates = r.removeLastState(r.previousStates)
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize will return the session as serialized bytes so it can be
|
||||
// persistently stored.
|
||||
func (r *Session) Serialize() []byte {
|
||||
return r.serializer.Serialize(r.Structure())
|
||||
}
|
||||
|
||||
// prependStates takes an array/slice of states and prepends it with
|
||||
// the given session state.
|
||||
func (r *Session) prependStates(states []*State, sessionState *State) []*State {
|
||||
return append([]*State{sessionState}, states...)
|
||||
}
|
||||
|
||||
// removeLastState takes an array/slice of states and removes the
|
||||
// last element from it.
|
||||
func (r *Session) removeLastState(states []*State) []*State {
|
||||
return states[:len(states)-1]
|
||||
}
|
||||
|
||||
// Structure will return a simple serializable session structure
|
||||
// from the given structure. This is used for serialization to persistently
|
||||
// store a session record.
|
||||
func (r *Session) Structure() *SessionStructure {
|
||||
previousStates := make([]*StateStructure, len(r.previousStates))
|
||||
for i := range r.previousStates {
|
||||
previousStates[i] = r.previousStates[i].structure()
|
||||
}
|
||||
return &SessionStructure{
|
||||
SessionState: r.sessionState.structure(),
|
||||
PreviousStates: previousStates,
|
||||
}
|
||||
}
|
531
vendor/go.mau.fi/libsignal/state/record/SessionState.go
vendored
Normal file
531
vendor/go.mau.fi/libsignal/state/record/SessionState.go
vendored
Normal file
@ -0,0 +1,531 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/kdf"
|
||||
"go.mau.fi/libsignal/keys/chain"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
"go.mau.fi/libsignal/keys/root"
|
||||
"go.mau.fi/libsignal/keys/session"
|
||||
"go.mau.fi/libsignal/logger"
|
||||
"go.mau.fi/libsignal/util/errorhelper"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
const maxMessageKeys int = 2000
|
||||
const maxReceiverChains int = 5
|
||||
|
||||
// StateSerializer is an interface for serializing and deserializing
|
||||
// a Signal State into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type StateSerializer interface {
|
||||
Serialize(state *StateStructure) []byte
|
||||
Deserialize(serialized []byte) (*StateStructure, error)
|
||||
}
|
||||
|
||||
// NewStateFromBytes will return a Signal State from the given
|
||||
// bytes using the given serializer.
|
||||
func NewStateFromBytes(serialized []byte, serializer StateSerializer) (*State, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
stateStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewStateFromStructure(stateStructure, serializer)
|
||||
}
|
||||
|
||||
// NewState returns a new session state.
|
||||
func NewState(serializer StateSerializer) *State {
|
||||
return &State{serializer: serializer}
|
||||
}
|
||||
|
||||
// NewStateFromStructure will return a new session state with the
|
||||
// given state structure.
|
||||
func NewStateFromStructure(structure *StateStructure, serializer StateSerializer) (*State, error) {
|
||||
// Keep a list of errors, so they can be handled once.
|
||||
errors := errorhelper.NewMultiError()
|
||||
|
||||
// Convert our ecc keys from bytes into object form.
|
||||
localIdentityPublic, err := ecc.DecodePoint(structure.LocalIdentityPublic, 0)
|
||||
errors.Add(err)
|
||||
remoteIdentityPublic, err := ecc.DecodePoint(structure.RemoteIdentityPublic, 0)
|
||||
errors.Add(err)
|
||||
senderBaseKey, err := ecc.DecodePoint(structure.SenderBaseKey, 0)
|
||||
errors.Add(err)
|
||||
var pendingPreKey *PendingPreKey
|
||||
if structure.PendingPreKey != nil {
|
||||
pendingPreKey, err = NewPendingPreKeyFromStruct(structure.PendingPreKey)
|
||||
errors.Add(err)
|
||||
}
|
||||
senderChain, err := NewChainFromStructure(structure.SenderChain)
|
||||
errors.Add(err)
|
||||
|
||||
// Build our receiver chains from structure.
|
||||
receiverChains := make([]*Chain, len(structure.ReceiverChains))
|
||||
for i := range structure.ReceiverChains {
|
||||
receiverChains[i], err = NewChainFromStructure(structure.ReceiverChains[i])
|
||||
errors.Add(err)
|
||||
}
|
||||
|
||||
// Handle any errors. The first error will always be returned if there are multiple.
|
||||
if errors.HasErrors() {
|
||||
return nil, errors
|
||||
}
|
||||
|
||||
// Build our state object.
|
||||
state := &State{
|
||||
localIdentityPublic: identity.NewKey(localIdentityPublic),
|
||||
localRegistrationID: structure.LocalRegistrationID,
|
||||
needsRefresh: structure.NeedsRefresh,
|
||||
pendingKeyExchange: NewPendingKeyExchangeFromStruct(structure.PendingKeyExchange),
|
||||
pendingPreKey: pendingPreKey,
|
||||
previousCounter: structure.PreviousCounter,
|
||||
receiverChains: receiverChains,
|
||||
remoteIdentityPublic: identity.NewKey(remoteIdentityPublic),
|
||||
remoteRegistrationID: structure.RemoteRegistrationID,
|
||||
rootKey: root.NewKey(kdf.DeriveSecrets, structure.RootKey),
|
||||
senderBaseKey: senderBaseKey,
|
||||
senderChain: senderChain,
|
||||
serializer: serializer,
|
||||
sessionVersion: structure.SessionVersion,
|
||||
}
|
||||
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// StateStructure is the structure of a session state. Fields are public
|
||||
// to be used for serialization and deserialization.
|
||||
type StateStructure struct {
|
||||
LocalIdentityPublic []byte
|
||||
LocalRegistrationID uint32
|
||||
NeedsRefresh bool
|
||||
PendingKeyExchange *PendingKeyExchangeStructure
|
||||
PendingPreKey *PendingPreKeyStructure
|
||||
PreviousCounter uint32
|
||||
ReceiverChains []*ChainStructure
|
||||
RemoteIdentityPublic []byte
|
||||
RemoteRegistrationID uint32
|
||||
RootKey []byte
|
||||
SenderBaseKey []byte
|
||||
SenderChain *ChainStructure
|
||||
SessionVersion int
|
||||
}
|
||||
|
||||
// State is a session state that contains the structure for
|
||||
// all sessions. Session states are contained inside session records.
|
||||
// The session state is implemented as a struct rather than protobuffers
|
||||
// to allow other serialization methods.
|
||||
type State struct {
|
||||
localIdentityPublic *identity.Key
|
||||
localRegistrationID uint32
|
||||
needsRefresh bool
|
||||
pendingKeyExchange *PendingKeyExchange
|
||||
pendingPreKey *PendingPreKey
|
||||
previousCounter uint32
|
||||
receiverChains []*Chain
|
||||
remoteIdentityPublic *identity.Key
|
||||
remoteRegistrationID uint32
|
||||
rootKey *root.Key
|
||||
senderBaseKey ecc.ECPublicKeyable
|
||||
senderChain *Chain
|
||||
serializer StateSerializer
|
||||
sessionVersion int
|
||||
}
|
||||
|
||||
// SenderBaseKey returns the sender's base key in bytes.
|
||||
func (s *State) SenderBaseKey() []byte {
|
||||
if s.senderBaseKey == nil {
|
||||
return nil
|
||||
}
|
||||
return s.senderBaseKey.Serialize()
|
||||
}
|
||||
|
||||
// SetSenderBaseKey sets the sender's base key with the given bytes.
|
||||
func (s *State) SetSenderBaseKey(senderBaseKey []byte) {
|
||||
s.senderBaseKey, _ = ecc.DecodePoint(senderBaseKey, 0)
|
||||
}
|
||||
|
||||
// Version returns the session's version.
|
||||
func (s *State) Version() int {
|
||||
return s.sessionVersion
|
||||
}
|
||||
|
||||
// SetVersion sets the session state's version number.
|
||||
func (s *State) SetVersion(version int) {
|
||||
s.sessionVersion = version
|
||||
}
|
||||
|
||||
// RemoteIdentityKey returns the identity key of the remote user.
|
||||
func (s *State) RemoteIdentityKey() *identity.Key {
|
||||
return s.remoteIdentityPublic
|
||||
}
|
||||
|
||||
// SetRemoteIdentityKey sets this session's identity key for the remote
|
||||
// user.
|
||||
func (s *State) SetRemoteIdentityKey(identityKey *identity.Key) {
|
||||
s.remoteIdentityPublic = identityKey
|
||||
}
|
||||
|
||||
// LocalIdentityKey returns the session's identity key for the local
|
||||
// user.
|
||||
func (s *State) LocalIdentityKey() *identity.Key {
|
||||
return s.localIdentityPublic
|
||||
}
|
||||
|
||||
// SetLocalIdentityKey sets the session's identity key for the local
|
||||
// user.
|
||||
func (s *State) SetLocalIdentityKey(identityKey *identity.Key) {
|
||||
s.localIdentityPublic = identityKey
|
||||
}
|
||||
|
||||
// PreviousCounter returns the counter of the previous message.
|
||||
func (s *State) PreviousCounter() uint32 {
|
||||
return s.previousCounter
|
||||
}
|
||||
|
||||
// SetPreviousCounter sets the counter for the previous message.
|
||||
func (s *State) SetPreviousCounter(previousCounter uint32) {
|
||||
s.previousCounter = previousCounter
|
||||
}
|
||||
|
||||
// RootKey returns the root key for the session.
|
||||
func (s *State) RootKey() session.RootKeyable {
|
||||
return s.rootKey
|
||||
}
|
||||
|
||||
// SetRootKey sets the root key for the session.
|
||||
func (s *State) SetRootKey(rootKey session.RootKeyable) {
|
||||
s.rootKey = rootKey.(*root.Key)
|
||||
}
|
||||
|
||||
// SenderRatchetKey returns the public ratchet key of the sender.
|
||||
func (s *State) SenderRatchetKey() ecc.ECPublicKeyable {
|
||||
return s.senderChain.senderRatchetKeyPair.PublicKey()
|
||||
}
|
||||
|
||||
// SenderRatchetKeyPair returns the public/private ratchet key pair
|
||||
// of the sender.
|
||||
func (s *State) SenderRatchetKeyPair() *ecc.ECKeyPair {
|
||||
return s.senderChain.senderRatchetKeyPair
|
||||
}
|
||||
|
||||
// HasReceiverChain will check to see if the session state has
|
||||
// the given ephemeral key.
|
||||
func (s *State) HasReceiverChain(senderEphemeral ecc.ECPublicKeyable) bool {
|
||||
return s.receiverChain(senderEphemeral) != nil
|
||||
}
|
||||
|
||||
// HasSenderChain will check to see if the session state has a
|
||||
// sender chain.
|
||||
func (s *State) HasSenderChain() bool {
|
||||
return s.senderChain != nil
|
||||
}
|
||||
|
||||
// receiverChain will loop through the session state's receiver chains
|
||||
// and compare the given ephemeral key. If it is found, then the chain
|
||||
// and index will be returned as a pair.
|
||||
func (s *State) receiverChain(senderEphemeral ecc.ECPublicKeyable) *ReceiverChainPair {
|
||||
receiverChains := s.receiverChains
|
||||
|
||||
for i, receiverChain := range receiverChains {
|
||||
chainSenderRatchetKey, err := ecc.DecodePoint(receiverChain.senderRatchetKeyPair.PublicKey().Serialize(), 0)
|
||||
if err != nil {
|
||||
logger.Error("Error getting receiverchain: ", err)
|
||||
}
|
||||
|
||||
// If the chainSenderRatchetKey equals our senderEphemeral key, return it.
|
||||
if chainSenderRatchetKey.PublicKey() == senderEphemeral.PublicKey() {
|
||||
return NewReceiverChainPair(receiverChain, i)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReceiverChainKey will use the given ephemeral key to generate a new
|
||||
// chain key.
|
||||
func (s *State) ReceiverChainKey(senderEphemeral ecc.ECPublicKeyable) *chain.Key {
|
||||
receiverChainAndIndex := s.receiverChain(senderEphemeral)
|
||||
receiverChain := receiverChainAndIndex.ReceiverChain
|
||||
|
||||
if receiverChainAndIndex == nil || receiverChain == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return chain.NewKey(
|
||||
kdf.DeriveSecrets,
|
||||
receiverChain.chainKey.Key(),
|
||||
receiverChain.chainKey.Index(),
|
||||
)
|
||||
}
|
||||
|
||||
// AddReceiverChain will add the given ratchet key and chain key to the session
|
||||
// state.
|
||||
func (s *State) AddReceiverChain(senderRatchetKey ecc.ECPublicKeyable, chainKey session.ChainKeyable) {
|
||||
// Create a keypair structure with our sender ratchet key.
|
||||
senderKey := ecc.NewECKeyPair(senderRatchetKey, nil)
|
||||
|
||||
// Create a Chain state object that will hold our sender key, chain key, and
|
||||
// message keys.
|
||||
chain := NewChain(senderKey, chainKey.(*chain.Key), []*message.Keys{})
|
||||
|
||||
// Add the Chain state to our list of receiver chain states.
|
||||
s.receiverChains = append(s.receiverChains, chain)
|
||||
|
||||
// If our list of receiver chains is too big, delete the oldest entry.
|
||||
if len(s.receiverChains) > maxReceiverChains {
|
||||
i := 0
|
||||
s.receiverChains = append(s.receiverChains[:i], s.receiverChains[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// SetSenderChain will set the given ratchet key pair and chain key for this session
|
||||
// state.
|
||||
func (s *State) SetSenderChain(senderRatchetKeyPair *ecc.ECKeyPair, chainKey session.ChainKeyable) {
|
||||
// Create a Chain state object that will hold our sender key, chain key, and
|
||||
// message keys.
|
||||
chain := NewChain(senderRatchetKeyPair, chainKey.(*chain.Key), []*message.Keys{})
|
||||
|
||||
// Set the sender chain.
|
||||
s.senderChain = chain
|
||||
}
|
||||
|
||||
// SenderChainKey will return the chain key of the session state.
|
||||
func (s *State) SenderChainKey() session.ChainKeyable {
|
||||
chainKey := s.senderChain.chainKey
|
||||
return chain.NewKey(kdf.DeriveSecrets, chainKey.Key(), chainKey.Index())
|
||||
}
|
||||
|
||||
// SetSenderChainKey will set the chain key in the chain state for this session to
|
||||
// the given chain key.
|
||||
func (s *State) SetSenderChainKey(nextChainKey session.ChainKeyable) {
|
||||
senderChain := s.senderChain
|
||||
senderChain.SetChainKey(nextChainKey.(*chain.Key))
|
||||
}
|
||||
|
||||
// HasMessageKeys returns true if we have message keys associated with the given
|
||||
// sender key and counter.
|
||||
func (s *State) HasMessageKeys(senderEphemeral ecc.ECPublicKeyable, counter uint32) bool {
|
||||
// Get our chain state that has our chain key.
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
receiverChain := chainAndIndex.ReceiverChain
|
||||
|
||||
// If the chain is empty, we don't have any message keys.
|
||||
if receiverChain == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Get our message keys from our receiver chain.
|
||||
messageKeyList := receiverChain.MessageKeys()
|
||||
|
||||
// Loop through our message keys and compare its index with the
|
||||
// given counter.
|
||||
for _, messageKey := range messageKeyList {
|
||||
if messageKey.Index() == counter {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// RemoveMessageKeys removes the message key with the given sender key and
|
||||
// counter. It will return the removed message key.
|
||||
func (s *State) RemoveMessageKeys(senderEphemeral ecc.ECPublicKeyable, counter uint32) *message.Keys {
|
||||
// Get our chain state that has our chain key.
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainKey := chainAndIndex.ReceiverChain
|
||||
|
||||
// If the chain is empty, we don't have any message keys.
|
||||
if chainKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get our message keys from our receiver chain.
|
||||
messageKeyList := chainKey.MessageKeys()
|
||||
|
||||
// Loop through our message keys and compare its index with the
|
||||
// given counter. When we find a match, remove it from our list.
|
||||
var rmIndex int
|
||||
for i, messageKey := range messageKeyList {
|
||||
if messageKey.Index() == counter {
|
||||
rmIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Retrive the message key
|
||||
messageKey := chainKey.messageKeys[rmIndex]
|
||||
|
||||
// Delete the message key from the given position.
|
||||
chainKey.messageKeys = append(chainKey.messageKeys[:rmIndex], chainKey.messageKeys[rmIndex+1:]...)
|
||||
|
||||
return message.NewKeys(
|
||||
messageKey.CipherKey(),
|
||||
messageKey.MacKey(),
|
||||
messageKey.Iv(),
|
||||
messageKey.Index(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetMessageKeys will update the chain associated with the given sender key with
|
||||
// the given message keys.
|
||||
func (s *State) SetMessageKeys(senderEphemeral ecc.ECPublicKeyable, messageKeys *message.Keys) {
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainState := chainAndIndex.ReceiverChain
|
||||
|
||||
// Add the message keys to our chain state.
|
||||
chainState.AddMessageKeys(
|
||||
message.NewKeys(
|
||||
messageKeys.CipherKey(),
|
||||
messageKeys.MacKey(),
|
||||
messageKeys.Iv(),
|
||||
messageKeys.Index(),
|
||||
),
|
||||
)
|
||||
|
||||
if len(chainState.MessageKeys()) > maxMessageKeys {
|
||||
chainState.PopFirstMessageKeys()
|
||||
}
|
||||
}
|
||||
|
||||
// SetReceiverChainKey sets the session's receiver chain key with the given chain key
|
||||
// associated with the given senderEphemeral key.
|
||||
func (s *State) SetReceiverChainKey(senderEphemeral ecc.ECPublicKeyable, chainKey session.ChainKeyable) {
|
||||
chainAndIndex := s.receiverChain(senderEphemeral)
|
||||
chainState := chainAndIndex.ReceiverChain
|
||||
chainState.SetChainKey(chainKey.(*chain.Key))
|
||||
}
|
||||
|
||||
// SetPendingKeyExchange will set the session's pending key exchange state to the given
|
||||
// sequence and key pairs.
|
||||
func (s *State) SetPendingKeyExchange(sequence uint32, ourBaseKey, ourRatchetKey *ecc.ECKeyPair,
|
||||
ourIdentityKey *identity.KeyPair) {
|
||||
|
||||
s.pendingKeyExchange = NewPendingKeyExchange(
|
||||
sequence,
|
||||
ourBaseKey,
|
||||
ourRatchetKey,
|
||||
ourIdentityKey,
|
||||
)
|
||||
}
|
||||
|
||||
// PendingKeyExchangeSequence will return the session's pending key exchange sequence
|
||||
// number.
|
||||
func (s *State) PendingKeyExchangeSequence() uint32 {
|
||||
return s.pendingKeyExchange.sequence
|
||||
}
|
||||
|
||||
// PendingKeyExchangeBaseKeyPair will return the session's pending key exchange base keypair.
|
||||
func (s *State) PendingKeyExchangeBaseKeyPair() *ecc.ECKeyPair {
|
||||
return s.pendingKeyExchange.localBaseKeyPair
|
||||
}
|
||||
|
||||
// PendingKeyExchangeRatchetKeyPair will return the session's pending key exchange ratchet
|
||||
// keypair.
|
||||
func (s *State) PendingKeyExchangeRatchetKeyPair() *ecc.ECKeyPair {
|
||||
return s.pendingKeyExchange.localRatchetKeyPair
|
||||
}
|
||||
|
||||
// PendingKeyExchangeIdentityKeyPair will return the session's pending key exchange identity
|
||||
// keypair.
|
||||
func (s *State) PendingKeyExchangeIdentityKeyPair() *identity.KeyPair {
|
||||
return s.pendingKeyExchange.localIdentityKeyPair
|
||||
}
|
||||
|
||||
// HasPendingKeyExchange will return true if there is a valid pending key exchange waiting.
|
||||
func (s *State) HasPendingKeyExchange() bool {
|
||||
return s.pendingKeyExchange != nil
|
||||
}
|
||||
|
||||
// SetUnacknowledgedPreKeyMessage will return unacknowledged pre key message with the
|
||||
// given key ids and base key.
|
||||
func (s *State) SetUnacknowledgedPreKeyMessage(preKeyID *optional.Uint32, signedPreKeyID uint32, baseKey ecc.ECPublicKeyable) {
|
||||
s.pendingPreKey = NewPendingPreKey(
|
||||
preKeyID,
|
||||
signedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
}
|
||||
|
||||
// HasUnacknowledgedPreKeyMessage will return true if this session has an unacknowledged
|
||||
// pre key message.
|
||||
func (s *State) HasUnacknowledgedPreKeyMessage() bool {
|
||||
return s.pendingPreKey != nil
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItems will return the session's unacknowledged pre key messages.
|
||||
func (s *State) UnackPreKeyMessageItems() (*UnackPreKeyMessageItems, error) {
|
||||
preKeyID := s.pendingPreKey.preKeyID
|
||||
signedPreKeyID := s.pendingPreKey.signedPreKeyID
|
||||
baseKey, err := ecc.DecodePoint(s.pendingPreKey.baseKey.Serialize(), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewUnackPreKeyMessageItems(preKeyID, signedPreKeyID, baseKey), nil
|
||||
}
|
||||
|
||||
// ClearUnackPreKeyMessage will clear the session's pending pre key.
|
||||
func (s *State) ClearUnackPreKeyMessage() {
|
||||
s.pendingPreKey = nil
|
||||
}
|
||||
|
||||
// SetRemoteRegistrationID sets the remote user's registration id.
|
||||
func (s *State) SetRemoteRegistrationID(registrationID uint32) {
|
||||
s.remoteRegistrationID = registrationID
|
||||
}
|
||||
|
||||
// RemoteRegistrationID returns the remote user's registration id.
|
||||
func (s *State) RemoteRegistrationID() uint32 {
|
||||
return s.remoteRegistrationID
|
||||
}
|
||||
|
||||
// SetLocalRegistrationID sets the local user's registration id.
|
||||
func (s *State) SetLocalRegistrationID(registrationID uint32) {
|
||||
s.localRegistrationID = registrationID
|
||||
}
|
||||
|
||||
// LocalRegistrationID returns the local user's registration id.
|
||||
func (s *State) LocalRegistrationID() uint32 {
|
||||
return s.localRegistrationID
|
||||
}
|
||||
|
||||
// Serialize will return the state as bytes using the given serializer.
|
||||
func (s *State) Serialize() []byte {
|
||||
return s.serializer.Serialize(s.structure())
|
||||
}
|
||||
|
||||
// structure will return a serializable structure of the
|
||||
// the given state so it can be persistently stored.
|
||||
func (s *State) structure() *StateStructure {
|
||||
// Convert our receiver chains into a serializeable structure
|
||||
receiverChains := make([]*ChainStructure, len(s.receiverChains))
|
||||
for i := range s.receiverChains {
|
||||
receiverChains[i] = s.receiverChains[i].structure()
|
||||
}
|
||||
|
||||
// Convert our pending key exchange into a serializeable structure
|
||||
var pendingKeyExchange *PendingKeyExchangeStructure
|
||||
if s.pendingKeyExchange != nil {
|
||||
pendingKeyExchange = s.pendingKeyExchange.structure()
|
||||
}
|
||||
|
||||
// Build and return our state structure.
|
||||
return &StateStructure{
|
||||
LocalIdentityPublic: s.localIdentityPublic.Serialize(),
|
||||
LocalRegistrationID: s.localRegistrationID,
|
||||
NeedsRefresh: s.needsRefresh,
|
||||
PendingKeyExchange: pendingKeyExchange,
|
||||
PendingPreKey: s.pendingPreKey.structure(),
|
||||
PreviousCounter: s.previousCounter,
|
||||
ReceiverChains: receiverChains,
|
||||
RemoteIdentityPublic: s.remoteIdentityPublic.Serialize(),
|
||||
RemoteRegistrationID: s.remoteRegistrationID,
|
||||
RootKey: s.rootKey.Bytes(),
|
||||
SenderBaseKey: s.senderBaseKey.Serialize(),
|
||||
SenderChain: s.senderChain.structure(),
|
||||
SessionVersion: s.sessionVersion,
|
||||
}
|
||||
}
|
112
vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
vendored
Normal file
112
vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/bytehelper"
|
||||
)
|
||||
|
||||
// SignedPreKeySerializer is an interface for serializing and deserializing
|
||||
// SignedPreKey objects into bytes. An implementation of this interface should be
|
||||
// used to encode/decode the object into JSON, Protobuffers, etc.
|
||||
type SignedPreKeySerializer interface {
|
||||
Serialize(signedPreKey *SignedPreKeyStructure) []byte
|
||||
Deserialize(serialized []byte) (*SignedPreKeyStructure, error)
|
||||
}
|
||||
|
||||
// NewSignedPreKeyFromBytes will return a signed prekey record from the given
|
||||
// bytes using the given serializer.
|
||||
func NewSignedPreKeyFromBytes(serialized []byte, serializer SignedPreKeySerializer) (*SignedPreKey, error) {
|
||||
// Use the given serializer to decode the signal message.
|
||||
signedPreKeyStructure, err := serializer.Deserialize(serialized)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSignedPreKeyFromStruct(signedPreKeyStructure, serializer)
|
||||
}
|
||||
|
||||
// NewSignedPreKeyFromStruct returns a SignedPreKey record using the given
|
||||
// serializable structure.
|
||||
func NewSignedPreKeyFromStruct(structure *SignedPreKeyStructure,
|
||||
serializer SignedPreKeySerializer) (*SignedPreKey, error) {
|
||||
|
||||
// Create the signed prekey record from the structure.
|
||||
signedPreKey := &SignedPreKey{
|
||||
structure: *structure,
|
||||
serializer: serializer,
|
||||
signature: bytehelper.SliceToArray64(structure.Signature),
|
||||
}
|
||||
|
||||
// Generate the ECC key from bytes.
|
||||
publicKey := ecc.NewDjbECPublicKey(bytehelper.SliceToArray(structure.PublicKey))
|
||||
privateKey := ecc.NewDjbECPrivateKey(bytehelper.SliceToArray(structure.PrivateKey))
|
||||
keyPair := ecc.NewECKeyPair(publicKey, privateKey)
|
||||
signedPreKey.keyPair = keyPair
|
||||
|
||||
return signedPreKey, nil
|
||||
}
|
||||
|
||||
// NewSignedPreKey record creates a new signed pre key record
|
||||
// with the given properties.
|
||||
func NewSignedPreKey(id uint32, timestamp int64, keyPair *ecc.ECKeyPair,
|
||||
sig [64]byte, serializer SignedPreKeySerializer) *SignedPreKey {
|
||||
|
||||
return &SignedPreKey{
|
||||
structure: SignedPreKeyStructure{
|
||||
ID: id,
|
||||
Timestamp: timestamp,
|
||||
PublicKey: keyPair.PublicKey().Serialize(),
|
||||
PrivateKey: bytehelper.ArrayToSlice(keyPair.PrivateKey().Serialize()),
|
||||
Signature: bytehelper.ArrayToSlice64(sig),
|
||||
},
|
||||
keyPair: keyPair,
|
||||
signature: sig,
|
||||
serializer: serializer,
|
||||
}
|
||||
}
|
||||
|
||||
// SignedPreKeyStructure is a flat structure of a signed pre key, used
|
||||
// for serialization and deserialization.
|
||||
type SignedPreKeyStructure struct {
|
||||
ID uint32
|
||||
PublicKey []byte
|
||||
PrivateKey []byte
|
||||
Signature []byte
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
// SignedPreKey record is a structure for storing a signed
|
||||
// pre key in a SignedPreKey store.
|
||||
type SignedPreKey struct {
|
||||
structure SignedPreKeyStructure
|
||||
keyPair *ecc.ECKeyPair
|
||||
signature [64]byte
|
||||
serializer SignedPreKeySerializer
|
||||
}
|
||||
|
||||
// ID returns the record's id.
|
||||
func (s *SignedPreKey) ID() uint32 {
|
||||
return s.structure.ID
|
||||
}
|
||||
|
||||
// Timestamp returns the record's timestamp
|
||||
func (s *SignedPreKey) Timestamp() int64 {
|
||||
return s.structure.Timestamp
|
||||
}
|
||||
|
||||
// KeyPair returns the signed pre key record's key pair.
|
||||
func (s *SignedPreKey) KeyPair() *ecc.ECKeyPair {
|
||||
return s.keyPair
|
||||
}
|
||||
|
||||
// Signature returns the record's signed prekey signature.
|
||||
func (s *SignedPreKey) Signature() [64]byte {
|
||||
return s.signature
|
||||
}
|
||||
|
||||
// Serialize uses the SignedPreKey serializer to return the SignedPreKey
|
||||
// as serialized bytes.
|
||||
func (s *SignedPreKey) Serialize() []byte {
|
||||
structure := s.structure
|
||||
return s.serializer.Serialize(&structure)
|
||||
}
|
69
vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
vendored
Normal file
69
vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
package record
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/util/optional"
|
||||
)
|
||||
|
||||
// NewUnackPreKeyMessageItems returns message items that are unacknowledged.
|
||||
func NewUnackPreKeyMessageItems(preKeyID *optional.Uint32, signedPreKeyID uint32,
|
||||
baseKey ecc.ECPublicKeyable) *UnackPreKeyMessageItems {
|
||||
|
||||
return &UnackPreKeyMessageItems{
|
||||
preKeyID: preKeyID,
|
||||
signedPreKeyID: signedPreKeyID,
|
||||
baseKey: baseKey,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUnackPreKeyMessageItemsFromStruct will return a new unacknowledged prekey
|
||||
// message items object from the given structure.
|
||||
func NewUnackPreKeyMessageItemsFromStruct(structure *UnackPreKeyMessageItemsStructure) *UnackPreKeyMessageItems {
|
||||
baseKey, _ := ecc.DecodePoint(structure.BaseKey, 0)
|
||||
return NewUnackPreKeyMessageItems(
|
||||
structure.PreKeyID,
|
||||
structure.SignedPreKeyID,
|
||||
baseKey,
|
||||
)
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItemsStructure is a serializable structure for unackowledged
|
||||
// prekey message items.
|
||||
type UnackPreKeyMessageItemsStructure struct {
|
||||
PreKeyID *optional.Uint32
|
||||
SignedPreKeyID uint32
|
||||
BaseKey []byte
|
||||
}
|
||||
|
||||
// UnackPreKeyMessageItems is a structure for messages that have not been
|
||||
// acknowledged.
|
||||
type UnackPreKeyMessageItems struct {
|
||||
preKeyID *optional.Uint32
|
||||
signedPreKeyID uint32
|
||||
baseKey ecc.ECPublicKeyable
|
||||
}
|
||||
|
||||
// PreKeyID returns the prekey id of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) PreKeyID() *optional.Uint32 {
|
||||
return u.preKeyID
|
||||
}
|
||||
|
||||
// SignedPreKeyID returns the signed prekey id of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) SignedPreKeyID() uint32 {
|
||||
return u.signedPreKeyID
|
||||
}
|
||||
|
||||
// BaseKey returns the ECC public key of the unacknowledged message.
|
||||
func (u *UnackPreKeyMessageItems) BaseKey() ecc.ECPublicKeyable {
|
||||
return u.baseKey
|
||||
}
|
||||
|
||||
// structure will return a serializable base structure
|
||||
// for unacknowledged prekey message items.
|
||||
func (u *UnackPreKeyMessageItems) structure() *UnackPreKeyMessageItemsStructure {
|
||||
return &UnackPreKeyMessageItemsStructure{
|
||||
PreKeyID: u.preKeyID,
|
||||
SignedPreKeyID: u.signedPreKeyID,
|
||||
BaseKey: u.baseKey.Serialize(),
|
||||
}
|
||||
}
|
3
vendor/go.mau.fi/libsignal/state/store/Doc.go
vendored
Normal file
3
vendor/go.mau.fi/libsignal/state/store/Doc.go
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// Package store provides the storage interfaces for storing the state of
|
||||
// ongoing double ratchet sessions and keys.
|
||||
package store
|
29
vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go
vendored
Normal file
29
vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
)
|
||||
|
||||
// IdentityKey provides an interface to identity information.
|
||||
type IdentityKey interface {
|
||||
// Get the local client's identity key pair.
|
||||
GetIdentityKeyPair() *identity.KeyPair
|
||||
|
||||
// Return the local client's registration ID.
|
||||
//
|
||||
// Clients should maintain a registration ID, a random number between 1 and 16380
|
||||
// that's generated once at install time.
|
||||
GetLocalRegistrationId() uint32
|
||||
|
||||
// Save a remote client's identity key in our identity store.
|
||||
SaveIdentity(address *protocol.SignalAddress, identityKey *identity.Key)
|
||||
|
||||
// Verify a remote client's identity key.
|
||||
//
|
||||
// Determine whether a remote client's identity is trusted. Trust is based on
|
||||
// 'trust on first use'. This means that an identity key is considered 'trusted'
|
||||
// if there is no entry for the recipient in the local store, or if it matches the
|
||||
// saved key for a recipient in the local store.
|
||||
IsTrustedIdentity(address *protocol.SignalAddress, identityKey *identity.Key) bool
|
||||
}
|
21
vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go
vendored
Normal file
21
vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/keys/message"
|
||||
)
|
||||
|
||||
// MessageKey store is an interface describing the optional local storage
|
||||
// of message keys.
|
||||
type MessageKey interface {
|
||||
// Load a local message key by id
|
||||
LoadMessageKey(keyID uint32) *message.Keys
|
||||
|
||||
// Store a local message key
|
||||
StoreMessageKey(keyID uint32, key *message.Keys)
|
||||
|
||||
// Check to see if the store contains a message key with id.
|
||||
ContainsMessageKey(keyID uint32) bool
|
||||
|
||||
// Delete a message key from local storage.
|
||||
RemoveMessageKey(keyID uint32)
|
||||
}
|
21
vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go
vendored
Normal file
21
vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// PreKey store is an interface describing the local storage
|
||||
// of PreKeyRecords
|
||||
type PreKey interface {
|
||||
// Load a local PreKeyRecord
|
||||
LoadPreKey(preKeyID uint32) *record.PreKey
|
||||
|
||||
// Store a local PreKeyRecord
|
||||
StorePreKey(preKeyID uint32, preKeyRecord *record.PreKey)
|
||||
|
||||
// Check to see if the store contains a PreKeyRecord
|
||||
ContainsPreKey(preKeyID uint32) bool
|
||||
|
||||
// Delete a PreKeyRecord from local storage.
|
||||
RemovePreKey(preKeyID uint32)
|
||||
}
|
17
vendor/go.mau.fi/libsignal/state/store/SessionStore.go
vendored
Normal file
17
vendor/go.mau.fi/libsignal/state/store/SessionStore.go
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/protocol"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// Session store is an interface for the persistent storage of session
|
||||
// state information for remote clients.
|
||||
type Session interface {
|
||||
LoadSession(address *protocol.SignalAddress) *record.Session
|
||||
GetSubDeviceSessions(name string) []uint32
|
||||
StoreSession(remoteAddress *protocol.SignalAddress, record *record.Session)
|
||||
ContainsSession(remoteAddress *protocol.SignalAddress) bool
|
||||
DeleteSession(remoteAddress *protocol.SignalAddress)
|
||||
DeleteAllSessions()
|
||||
}
|
15
vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go
vendored
Normal file
15
vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/groups/state/store"
|
||||
)
|
||||
|
||||
// SignalProtocol store is an interface that implements the
|
||||
// methods for all stores needed in the Signal Protocol.
|
||||
type SignalProtocol interface {
|
||||
IdentityKey
|
||||
PreKey
|
||||
Session
|
||||
SignedPreKey
|
||||
store.SenderKey
|
||||
}
|
24
vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go
vendored
Normal file
24
vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// SignedPreKey store is an interface that describes how to persistently
|
||||
// store signed PreKeys.
|
||||
type SignedPreKey interface {
|
||||
// LoadSignedPreKey loads a local SignedPreKeyRecord
|
||||
LoadSignedPreKey(signedPreKeyID uint32) *record.SignedPreKey
|
||||
|
||||
// LoadSignedPreKeys loads all local SignedPreKeyRecords
|
||||
LoadSignedPreKeys() []*record.SignedPreKey
|
||||
|
||||
// Store a local SignedPreKeyRecord
|
||||
StoreSignedPreKey(signedPreKeyID uint32, record *record.SignedPreKey)
|
||||
|
||||
// Check to see if store contains the given record
|
||||
ContainsSignedPreKey(signedPreKeyID uint32) bool
|
||||
|
||||
// Delete a SignedPreKeyRecord from local storage
|
||||
RemoveSignedPreKey(signedPreKeyID uint32)
|
||||
}
|
97
vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go
vendored
Normal file
97
vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
package bytehelper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
// SliceToArray will convert byte slice to a 32 byte array
|
||||
func SliceToArray(bytes []byte) [32]byte {
|
||||
var byteArray [32]byte
|
||||
copy(byteArray[:], bytes)
|
||||
return byteArray
|
||||
}
|
||||
|
||||
// SliceToArray64 will convert byte slice to a 64 byte array
|
||||
func SliceToArray64(bytes []byte) [64]byte {
|
||||
var byteArray [64]byte
|
||||
copy(byteArray[:], bytes)
|
||||
return byteArray
|
||||
}
|
||||
|
||||
// ArrayToSlice will convert a 32 byte array to byte slice
|
||||
func ArrayToSlice(bytes [32]byte) []byte {
|
||||
return bytes[:]
|
||||
}
|
||||
|
||||
// ArrayToSlice64 will convert a 64 byte array to byte slice
|
||||
func ArrayToSlice64(bytes [64]byte) []byte {
|
||||
return bytes[:]
|
||||
}
|
||||
|
||||
// Split will take the given byte array and split it into half,
|
||||
// with the first half being "firstLength" in size and the second
|
||||
// half "secondLength" in size.
|
||||
func Split(input []byte, firstLength, secondLength int) [][]byte {
|
||||
parts := make([][]byte, 2)
|
||||
|
||||
parts[0] = make([]byte, firstLength)
|
||||
copy(parts[0], input[:firstLength])
|
||||
|
||||
parts[1] = make([]byte, secondLength)
|
||||
copy(parts[1], input[firstLength:])
|
||||
|
||||
return parts
|
||||
}
|
||||
|
||||
// SplitThree will take the given byte array and split it into thirds,
|
||||
// with the first third being "firstLength" in size, the second third
|
||||
// being "secondLength" in size, and the last third being "thirdLength"
|
||||
// in size.
|
||||
func SplitThree(input []byte, firstLength, secondLength, thirdLength int) ([][]byte, error) {
|
||||
if input == nil || firstLength < 0 || secondLength < 0 || thirdLength < 0 ||
|
||||
len(input) < firstLength+secondLength+thirdLength {
|
||||
|
||||
return nil, errors.New("Input too small: " + string(input))
|
||||
}
|
||||
|
||||
parts := make([][]byte, 3)
|
||||
|
||||
parts[0] = make([]byte, firstLength)
|
||||
copy(parts[0], input[:firstLength])
|
||||
|
||||
parts[1] = make([]byte, secondLength)
|
||||
copy(parts[1], input[firstLength:][:secondLength])
|
||||
|
||||
parts[2] = make([]byte, thirdLength)
|
||||
copy(parts[2], input[firstLength+secondLength:])
|
||||
|
||||
return parts, nil
|
||||
}
|
||||
|
||||
// Trim will trim the given byte array to the given length.
|
||||
func Trim(input []byte, length int) []byte {
|
||||
result := make([]byte, length)
|
||||
copy(result, input[:length])
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Bytes5ToInt64 will convert the given byte array and offset to an int64.
|
||||
func Bytes5ToInt64(bytes []byte, offset int) int64 {
|
||||
|
||||
value := (int64(bytes[offset]&0xff) << 32) |
|
||||
(int64(bytes[offset+1]&0xff) << 24) |
|
||||
(int64(bytes[offset+2]&0xff) << 16) |
|
||||
(int64(bytes[offset+3]&0xff) << 8) |
|
||||
int64(bytes[offset+4]&0xff)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// CopySlice returns a copy of the given bytes.
|
||||
func CopySlice(bytes []byte) []byte {
|
||||
cp := make([]byte, len(bytes))
|
||||
copy(cp, bytes)
|
||||
|
||||
return cp
|
||||
}
|
40
vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go
vendored
Normal file
40
vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
package errorhelper
|
||||
|
||||
// NewMultiError returns a new MultiError object.
|
||||
func NewMultiError() *MultiError {
|
||||
return &MultiError{
|
||||
errors: []error{},
|
||||
}
|
||||
}
|
||||
|
||||
// MultiError is a structure for holding multiple errors so they
|
||||
// can be checked at a later point.
|
||||
type MultiError struct {
|
||||
errors []error
|
||||
}
|
||||
|
||||
// Add will add the given error if it is not nil.
|
||||
func (m *MultiError) Add(err error) {
|
||||
if err != nil {
|
||||
m.errors = append(m.errors, err)
|
||||
}
|
||||
}
|
||||
|
||||
// HasErrors will return true if any non-nil errors have been
|
||||
// added.
|
||||
func (m *MultiError) HasErrors() bool {
|
||||
if len(m.errors) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Error will print the first error is encountered.
|
||||
func (m *MultiError) Error() string {
|
||||
if !m.HasErrors() {
|
||||
return ""
|
||||
}
|
||||
|
||||
return m.errors[0].Error()
|
||||
}
|
95
vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go
vendored
Normal file
95
vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
// Package keyhelper is based on: https://github.com/WhisperSystems/libsignal-protocol-java/blob/master/java/src/main/java/org/whispersystems/libsignal/util/KeyHelper.java
|
||||
package keyhelper
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"time"
|
||||
|
||||
"go.mau.fi/libsignal/ecc"
|
||||
"go.mau.fi/libsignal/keys/identity"
|
||||
"go.mau.fi/libsignal/state/record"
|
||||
)
|
||||
|
||||
// GenerateIdentityKeyPair generates an identity keypair used for
|
||||
// signing. Clients should only do this once at install time.
|
||||
func GenerateIdentityKeyPair() (*identity.KeyPair, error) {
|
||||
keyPair, err := ecc.GenerateKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
publicKey := identity.NewKey(keyPair.PublicKey())
|
||||
return identity.NewKeyPair(publicKey, keyPair.PrivateKey()), nil
|
||||
}
|
||||
|
||||
// GeneratePreKeys generates a list of PreKeys. Client shsould do this at
|
||||
// install time, and subsequently any time the list of PreKeys stored on
|
||||
// the server runs low.
|
||||
//
|
||||
// PreKeys IDs are shorts, so they will eventually be repeated. Clients
|
||||
// should store PreKeys in a circular buffer, so that they are repeated
|
||||
// as infrequently as possible.
|
||||
func GeneratePreKeys(start int, count int, serializer record.PreKeySerializer) ([]*record.PreKey, error) {
|
||||
var preKeys []*record.PreKey
|
||||
|
||||
for i := start; i <= count; i++ {
|
||||
key, err := ecc.GenerateKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
preKeys = append(preKeys, record.NewPreKey(uint32(i), key, serializer))
|
||||
}
|
||||
|
||||
return preKeys, nil
|
||||
}
|
||||
|
||||
// GenerateLastResortKey will generate the last resort PreKey. Clients should
|
||||
// do this only once, at install time, and durably store it for the length
|
||||
// of the install.
|
||||
func GenerateLastResortKey(serializer record.PreKeySerializer) (*record.PreKey, error) {
|
||||
keyPair, err := ecc.GenerateKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return record.NewPreKey(0, keyPair, serializer), nil
|
||||
}
|
||||
|
||||
// GenerateSignedPreKey generates a signed PreKey.
|
||||
func GenerateSignedPreKey(identityKeyPair *identity.KeyPair, signedPreKeyID uint32, serializer record.SignedPreKeySerializer) (*record.SignedPreKey, error) {
|
||||
keyPair, err := ecc.GenerateKeyPair()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signature := ecc.CalculateSignature(identityKeyPair.PrivateKey(), keyPair.PublicKey().Serialize())
|
||||
timestamp := time.Now().Unix()
|
||||
|
||||
return record.NewSignedPreKey(signedPreKeyID, timestamp, keyPair, signature, serializer), nil
|
||||
}
|
||||
|
||||
// GenerateRegistrationID generates a registration ID. Clients should only do
|
||||
// this once, at install time.
|
||||
func GenerateRegistrationID() uint32 {
|
||||
var n uint32
|
||||
binary.Read(rand.Reader, binary.LittleEndian, &n)
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
//---------- Group Stuff ----------------
|
||||
|
||||
func GenerateSenderSigningKey() (*ecc.ECKeyPair, error) {
|
||||
return ecc.GenerateKeyPair()
|
||||
}
|
||||
|
||||
func GenerateSenderKey() []byte {
|
||||
randBytes := make([]byte, 32)
|
||||
rand.Read(randBytes)
|
||||
return randBytes
|
||||
}
|
||||
|
||||
func GenerateSenderKeyID() uint32 {
|
||||
return GenerateRegistrationID()
|
||||
}
|
||||
|
||||
//---------- End Group Stuff --------------
|
4
vendor/go.mau.fi/libsignal/util/medium/Medium.go
vendored
Normal file
4
vendor/go.mau.fi/libsignal/util/medium/Medium.go
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
package medium
|
||||
|
||||
// MaxValue is the maximum possible integer value.
|
||||
const MaxValue uint32 = 0xFFFFFF
|
17
vendor/go.mau.fi/libsignal/util/optional/Integer.go
vendored
Normal file
17
vendor/go.mau.fi/libsignal/util/optional/Integer.go
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
package optional
|
||||
|
||||
// NewOptionalUint32 returns an optional Uint32 structure.
|
||||
func NewOptionalUint32(value uint32) *Uint32 {
|
||||
return &Uint32{Value: value, IsEmpty: false}
|
||||
}
|
||||
|
||||
func NewEmptyUint32() *Uint32 {
|
||||
return &Uint32{IsEmpty: true}
|
||||
}
|
||||
|
||||
// Uint32 is a simple structure for Uint32 values that can
|
||||
// optionally be nil.
|
||||
type Uint32 struct {
|
||||
Value uint32
|
||||
IsEmpty bool
|
||||
}
|
Reference in New Issue
Block a user