summaryrefslogtreecommitdiffstats
path: root/vendor/go.mau.fi/libsignal
diff options
context:
space:
mode:
authorWim <wim@42.be>2022-01-31 00:27:37 +0100
committerWim <wim@42.be>2022-03-20 14:57:48 +0100
commite3cafeaf9292f67459ff1d186f68283bfaedf2ae (patch)
treeb69c39620aa91dba695b3b935c6651c0fb37ce75 /vendor/go.mau.fi/libsignal
parente7b193788a56ee7cdb02a87a9db0ad6724ef66d5 (diff)
downloadmatterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.gz
matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.bz2
matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.zip
Add dependencies/vendor (whatsapp)
Diffstat (limited to 'vendor/go.mau.fi/libsignal')
-rw-r--r--vendor/go.mau.fi/libsignal/LICENSE674
-rw-r--r--vendor/go.mau.fi/libsignal/cipher/Cbc.go101
-rw-r--r--vendor/go.mau.fi/libsignal/cipher/Cipher.go105
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/Curve.go109
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go29
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go29
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go27
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go7
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go11
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go97
-rw-r--r--vendor/go.mau.fi/libsignal/groups/GroupCipher.go141
-rw-r--r--vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go84
-rw-r--r--vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go68
-rw-r--r--vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go89
-rw-r--r--vendor/go.mau.fi/libsignal/groups/state/record/Doc.go2
-rw-r--r--vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go149
-rw-r--r--vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go186
-rw-r--r--vendor/go.mau.fi/libsignal/groups/state/store/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go11
-rw-r--r--vendor/go.mau.fi/libsignal/kdf/HKDF.go47
-rw-r--r--vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go127
-rw-r--r--vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go47
-rw-r--r--vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go39
-rw-r--r--vendor/go.mau.fi/libsignal/keys/message/MessageKey.go91
-rw-r--r--vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go86
-rw-r--r--vendor/go.mau.fi/libsignal/keys/root/RootKey.go66
-rw-r--r--vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go29
-rw-r--r--vendor/go.mau.fi/libsignal/keys/session/Pair.go43
-rw-r--r--vendor/go.mau.fi/libsignal/logger/DefaultLogger.go85
-rw-r--r--vendor/go.mau.fi/libsignal/logger/Logger.go89
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go19
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go152
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go147
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go168
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go25
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/SignalMessage.go226
-rw-r--r--vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go38
-rw-r--r--vendor/go.mau.fi/libsignal/ratchet/Ratchet.go197
-rw-r--r--vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go106
-rw-r--r--vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go106
-rw-r--r--vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go18
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go245
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto14
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go303
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go1500
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto114
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go262
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/Serializer.go31
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go640
-rw-r--r--vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto45
-rw-r--r--vendor/go.mau.fi/libsignal/session/Session.go272
-rw-r--r--vendor/go.mau.fi/libsignal/session/SessionCipher.go366
-rw-r--r--vendor/go.mau.fi/libsignal/signalerror/errors.go37
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/ChainState.go157
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go91
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go62
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go90
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/SessionRecord.go197
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/SessionState.go531
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go112
-rw-r--r--vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go69
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/Doc.go3
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go29
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go21
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go21
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/SessionStore.go17
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go15
-rw-r--r--vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go24
-rw-r--r--vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go97
-rw-r--r--vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go40
-rw-r--r--vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go95
-rw-r--r--vendor/go.mau.fi/libsignal/util/medium/Medium.go4
-rw-r--r--vendor/go.mau.fi/libsignal/util/optional/Integer.go17
77 files changed, 9406 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/LICENSE b/vendor/go.mau.fi/libsignal/LICENSE
new file mode 100644
index 00000000..eecbf2cf
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/LICENSE
@@ -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>.
diff --git a/vendor/go.mau.fi/libsignal/cipher/Cbc.go b/vendor/go.mau.fi/libsignal/cipher/Cbc.go
new file mode 100644
index 00000000..6a6db5df
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/cipher/Cbc.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/cipher/Cipher.go b/vendor/go.mau.fi/libsignal/cipher/Cipher.go
new file mode 100644
index 00000000..edfb428f
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/cipher/Cipher.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/Curve.go b/vendor/go.mau.fi/libsignal/ecc/Curve.go
new file mode 100644
index 00000000..f93cc39a
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/Curve.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go b/vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go
new file mode 100644
index 00000000..11757fb4
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go b/vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go
new file mode 100644
index 00000000..055692ca
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/Doc.go b/vendor/go.mau.fi/libsignal/ecc/Doc.go
new file mode 100644
index 00000000..06e2cac7
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/Doc.go
@@ -0,0 +1,3 @@
+// Package ecc provides a way to generate, sign, and use Elliptic-Curve
+// X25519 Cryptography keys.
+package ecc
diff --git a/vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go b/vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go
new file mode 100644
index 00000000..11103447
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go b/vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go
new file mode 100644
index 00000000..be3ddae5
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go
@@ -0,0 +1,7 @@
+package ecc
+
+// ECPrivateKeyable is an interface for all elliptic curve private keys.
+type ECPrivateKeyable interface {
+ Serialize() [32]byte
+ Type() int
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go b/vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go
new file mode 100644
index 00000000..9b71f050
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go b/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go
new file mode 100644
index 00000000..a9bd7b48
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go
@@ -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[:])
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/GroupCipher.go b/vendor/go.mau.fi/libsignal/groups/GroupCipher.go
new file mode 100644
index 00000000..b821f3c3
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/GroupCipher.go
@@ -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()
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go b/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go
new file mode 100644
index 00000000..2a5569b7
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go b/vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go
new file mode 100644
index 00000000..6d374465
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go
@@ -0,0 +1,3 @@
+// Package ratchet provides the methods necessary to establish a ratchet
+// session for group messaging.
+package ratchet
diff --git a/vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go b/vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go
new file mode 100644
index 00000000..a9530143
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go b/vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go
new file mode 100644
index 00000000..724059f2
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go b/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go
new file mode 100644
index 00000000..5a7d7307
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/state/record/Doc.go
@@ -0,0 +1,2 @@
+// Package record provides the state and record of a group session.
+package record
diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go
new file mode 100644
index 00000000..64d59068
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go
@@ -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,
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go
new file mode 100644
index 00000000..e3187c30
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go b/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go
new file mode 100644
index 00000000..8a23b446
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/state/store/Doc.go
@@ -0,0 +1,3 @@
+// Package store provides the storage interfaces for storing group sender
+// key records.
+package store
diff --git a/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go b/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go
new file mode 100644
index 00000000..a068df7c
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/kdf/HKDF.go b/vendor/go.mau.fi/libsignal/kdf/HKDF.go
new file mode 100644
index 00000000..168b18ac
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/kdf/HKDF.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go b/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go
new file mode 100644
index 00000000..0a5125df
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go b/vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go
new file mode 100644
index 00000000..127dbe16
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go
@@ -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()
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go b/vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go
new file mode 100644
index 00000000..1d401118
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go
@@ -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 {
+//}
diff --git a/vendor/go.mau.fi/libsignal/keys/message/MessageKey.go b/vendor/go.mau.fi/libsignal/keys/message/MessageKey.go
new file mode 100644
index 00000000..4eadffbe
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/message/MessageKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go b/vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go
new file mode 100644
index 00000000..04471673
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/root/RootKey.go b/vendor/go.mau.fi/libsignal/keys/root/RootKey.go
new file mode 100644
index 00000000..e925bc76
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/root/RootKey.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go b/vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go
new file mode 100644
index 00000000..6d73cb45
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/keys/session/Pair.go b/vendor/go.mau.fi/libsignal/keys/session/Pair.go
new file mode 100644
index 00000000..f6387ba8
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/keys/session/Pair.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/logger/DefaultLogger.go b/vendor/go.mau.fi/libsignal/logger/DefaultLogger.go
new file mode 100644
index 00000000..62515bff
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/logger/DefaultLogger.go
@@ -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, ",")
+}
diff --git a/vendor/go.mau.fi/libsignal/logger/Logger.go b/vendor/go.mau.fi/libsignal/logger/Logger.go
new file mode 100644
index 00000000..653320bf
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/logger/Logger.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go b/vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go
new file mode 100644
index 00000000..c8bd759a
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go
@@ -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
diff --git a/vendor/go.mau.fi/libsignal/protocol/Doc.go b/vendor/go.mau.fi/libsignal/protocol/Doc.go
new file mode 100644
index 00000000..3486bdfb
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/Doc.go
@@ -0,0 +1,3 @@
+// Package protocol provides address, group, and message structures that
+// the Signal protocol uses for sending encrypted messages.
+package protocol
diff --git a/vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go b/vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go
new file mode 100644
index 00000000..841d9d17
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go b/vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go
new file mode 100644
index 00000000..55adcede
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go b/vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go
new file mode 100644
index 00000000..cd69cea4
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go b/vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go
new file mode 100644
index 00000000..d9b6b684
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/SignalMessage.go b/vendor/go.mau.fi/libsignal/protocol/SignalMessage.go
new file mode 100644
index 00000000..fd348a3e
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/SignalMessage.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go b/vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go
new file mode 100644
index 00000000..468a3087
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go b/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go
new file mode 100644
index 00000000..df25beb3
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ratchet/Ratchet.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go b/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go
new file mode 100644
index 00000000..97822d19
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go b/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go
new file mode 100644
index 00000000..ca972956
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go b/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go
new file mode 100644
index 00000000..e7811de5
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go b/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go
new file mode 100644
index 00000000..1e90caac
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto b/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto
new file mode 100644
index 00000000..2003ec72
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto
@@ -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;
+} \ No newline at end of file
diff --git a/vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go b/vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go
new file mode 100644
index 00000000..1245fc42
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go b/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go
new file mode 100644
index 00000000..e7097399
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go
@@ -0,0 +1,1500 @@
+// From https://github.com/signalapp/libsignal-protocol-c/blob/master/protobuf/LocalStorageProtocol.proto
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.26.0
+// protoc v3.12.4
+// source: serialize/LocalStorageProtocol.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 SessionStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SessionVersion *uint32 `protobuf:"varint,1,opt,name=sessionVersion" json:"sessionVersion,omitempty"`
+ LocalIdentityPublic []byte `protobuf:"bytes,2,opt,name=localIdentityPublic" json:"localIdentityPublic,omitempty"`
+ RemoteIdentityPublic []byte `protobuf:"bytes,3,opt,name=remoteIdentityPublic" json:"remoteIdentityPublic,omitempty"`
+ RootKey []byte `protobuf:"bytes,4,opt,name=rootKey" json:"rootKey,omitempty"`
+ PreviousCounter *uint32 `protobuf:"varint,5,opt,name=previousCounter" json:"previousCounter,omitempty"`
+ SenderChain *SessionStructure_Chain `protobuf:"bytes,6,opt,name=senderChain" json:"senderChain,omitempty"`
+ ReceiverChains []*SessionStructure_Chain `protobuf:"bytes,7,rep,name=receiverChains" json:"receiverChains,omitempty"`
+ PendingKeyExchange *SessionStructure_PendingKeyExchange `protobuf:"bytes,8,opt,name=pendingKeyExchange" json:"pendingKeyExchange,omitempty"`
+ PendingPreKey *SessionStructure_PendingPreKey `protobuf:"bytes,9,opt,name=pendingPreKey" json:"pendingPreKey,omitempty"`
+ RemoteRegistrationId *uint32 `protobuf:"varint,10,opt,name=remoteRegistrationId" json:"remoteRegistrationId,omitempty"`
+ LocalRegistrationId *uint32 `protobuf:"varint,11,opt,name=localRegistrationId" json:"localRegistrationId,omitempty"`
+ NeedsRefresh *bool `protobuf:"varint,12,opt,name=needsRefresh" json:"needsRefresh,omitempty"`
+ AliceBaseKey []byte `protobuf:"bytes,13,opt,name=aliceBaseKey" json:"aliceBaseKey,omitempty"`
+}
+
+func (x *SessionStructure) Reset() {
+ *x = SessionStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure) ProtoMessage() {}
+
+func (x *SessionStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 SessionStructure.ProtoReflect.Descriptor instead.
+func (*SessionStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *SessionStructure) GetSessionVersion() uint32 {
+ if x != nil && x.SessionVersion != nil {
+ return *x.SessionVersion
+ }
+ return 0
+}
+
+func (x *SessionStructure) GetLocalIdentityPublic() []byte {
+ if x != nil {
+ return x.LocalIdentityPublic
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetRemoteIdentityPublic() []byte {
+ if x != nil {
+ return x.RemoteIdentityPublic
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetRootKey() []byte {
+ if x != nil {
+ return x.RootKey
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetPreviousCounter() uint32 {
+ if x != nil && x.PreviousCounter != nil {
+ return *x.PreviousCounter
+ }
+ return 0
+}
+
+func (x *SessionStructure) GetSenderChain() *SessionStructure_Chain {
+ if x != nil {
+ return x.SenderChain
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetReceiverChains() []*SessionStructure_Chain {
+ if x != nil {
+ return x.ReceiverChains
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetPendingKeyExchange() *SessionStructure_PendingKeyExchange {
+ if x != nil {
+ return x.PendingKeyExchange
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetPendingPreKey() *SessionStructure_PendingPreKey {
+ if x != nil {
+ return x.PendingPreKey
+ }
+ return nil
+}
+
+func (x *SessionStructure) GetRemoteRegistrationId() uint32 {
+ if x != nil && x.RemoteRegistrationId != nil {
+ return *x.RemoteRegistrationId
+ }
+ return 0
+}
+
+func (x *SessionStructure) GetLocalRegistrationId() uint32 {
+ if x != nil && x.LocalRegistrationId != nil {
+ return *x.LocalRegistrationId
+ }
+ return 0
+}
+
+func (x *SessionStructure) GetNeedsRefresh() bool {
+ if x != nil && x.NeedsRefresh != nil {
+ return *x.NeedsRefresh
+ }
+ return false
+}
+
+func (x *SessionStructure) GetAliceBaseKey() []byte {
+ if x != nil {
+ return x.AliceBaseKey
+ }
+ return nil
+}
+
+type RecordStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ CurrentSession *SessionStructure `protobuf:"bytes,1,opt,name=currentSession" json:"currentSession,omitempty"`
+ PreviousSessions []*SessionStructure `protobuf:"bytes,2,rep,name=previousSessions" json:"previousSessions,omitempty"`
+}
+
+func (x *RecordStructure) Reset() {
+ *x = RecordStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *RecordStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RecordStructure) ProtoMessage() {}
+
+func (x *RecordStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 RecordStructure.ProtoReflect.Descriptor instead.
+func (*RecordStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *RecordStructure) GetCurrentSession() *SessionStructure {
+ if x != nil {
+ return x.CurrentSession
+ }
+ return nil
+}
+
+func (x *RecordStructure) GetPreviousSessions() []*SessionStructure {
+ if x != nil {
+ return x.PreviousSessions
+ }
+ return nil
+}
+
+type PreKeyRecordStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id *uint32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
+ PublicKey []byte `protobuf:"bytes,2,opt,name=publicKey" json:"publicKey,omitempty"`
+ PrivateKey []byte `protobuf:"bytes,3,opt,name=privateKey" json:"privateKey,omitempty"`
+}
+
+func (x *PreKeyRecordStructure) Reset() {
+ *x = PreKeyRecordStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PreKeyRecordStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PreKeyRecordStructure) ProtoMessage() {}
+
+func (x *PreKeyRecordStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 PreKeyRecordStructure.ProtoReflect.Descriptor instead.
+func (*PreKeyRecordStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *PreKeyRecordStructure) GetId() uint32 {
+ if x != nil && x.Id != nil {
+ return *x.Id
+ }
+ return 0
+}
+
+func (x *PreKeyRecordStructure) GetPublicKey() []byte {
+ if x != nil {
+ return x.PublicKey
+ }
+ return nil
+}
+
+func (x *PreKeyRecordStructure) GetPrivateKey() []byte {
+ if x != nil {
+ return x.PrivateKey
+ }
+ return nil
+}
+
+type SignedPreKeyRecordStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Id *uint32 `protobuf:"varint,1,opt,name=id" json:"id,omitempty"`
+ PublicKey []byte `protobuf:"bytes,2,opt,name=publicKey" json:"publicKey,omitempty"`
+ PrivateKey []byte `protobuf:"bytes,3,opt,name=privateKey" json:"privateKey,omitempty"`
+ Signature []byte `protobuf:"bytes,4,opt,name=signature" json:"signature,omitempty"`
+ Timestamp *uint64 `protobuf:"fixed64,5,opt,name=timestamp" json:"timestamp,omitempty"`
+}
+
+func (x *SignedPreKeyRecordStructure) Reset() {
+ *x = SignedPreKeyRecordStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SignedPreKeyRecordStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SignedPreKeyRecordStructure) ProtoMessage() {}
+
+func (x *SignedPreKeyRecordStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 SignedPreKeyRecordStructure.ProtoReflect.Descriptor instead.
+func (*SignedPreKeyRecordStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *SignedPreKeyRecordStructure) GetId() uint32 {
+ if x != nil && x.Id != nil {
+ return *x.Id
+ }
+ return 0
+}
+
+func (x *SignedPreKeyRecordStructure) GetPublicKey() []byte {
+ if x != nil {
+ return x.PublicKey
+ }
+ return nil
+}
+
+func (x *SignedPreKeyRecordStructure) GetPrivateKey() []byte {
+ if x != nil {
+ return x.PrivateKey
+ }
+ return nil
+}
+
+func (x *SignedPreKeyRecordStructure) GetSignature() []byte {
+ if x != nil {
+ return x.Signature
+ }
+ return nil
+}
+
+func (x *SignedPreKeyRecordStructure) GetTimestamp() uint64 {
+ if x != nil && x.Timestamp != nil {
+ return *x.Timestamp
+ }
+ return 0
+}
+
+type IdentityKeyPairStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ PublicKey []byte `protobuf:"bytes,1,opt,name=publicKey" json:"publicKey,omitempty"`
+ PrivateKey []byte `protobuf:"bytes,2,opt,name=privateKey" json:"privateKey,omitempty"`
+}
+
+func (x *IdentityKeyPairStructure) Reset() {
+ *x = IdentityKeyPairStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *IdentityKeyPairStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*IdentityKeyPairStructure) ProtoMessage() {}
+
+func (x *IdentityKeyPairStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 IdentityKeyPairStructure.ProtoReflect.Descriptor instead.
+func (*IdentityKeyPairStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *IdentityKeyPairStructure) GetPublicKey() []byte {
+ if x != nil {
+ return x.PublicKey
+ }
+ return nil
+}
+
+func (x *IdentityKeyPairStructure) GetPrivateKey() []byte {
+ if x != nil {
+ return x.PrivateKey
+ }
+ return nil
+}
+
+type SenderKeyStateStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SenderKeyId *uint32 `protobuf:"varint,1,opt,name=senderKeyId" json:"senderKeyId,omitempty"`
+ SenderChainKey *SenderKeyStateStructure_SenderChainKey `protobuf:"bytes,2,opt,name=senderChainKey" json:"senderChainKey,omitempty"`
+ SenderSigningKey *SenderKeyStateStructure_SenderSigningKey `protobuf:"bytes,3,opt,name=senderSigningKey" json:"senderSigningKey,omitempty"`
+ SenderMessageKeys []*SenderKeyStateStructure_SenderMessageKey `protobuf:"bytes,4,rep,name=senderMessageKeys" json:"senderMessageKeys,omitempty"`
+}
+
+func (x *SenderKeyStateStructure) Reset() {
+ *x = SenderKeyStateStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SenderKeyStateStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SenderKeyStateStructure) ProtoMessage() {}
+
+func (x *SenderKeyStateStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_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 SenderKeyStateStructure.ProtoReflect.Descriptor instead.
+func (*SenderKeyStateStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *SenderKeyStateStructure) GetSenderKeyId() uint32 {
+ if x != nil && x.SenderKeyId != nil {
+ return *x.SenderKeyId
+ }
+ return 0
+}
+
+func (x *SenderKeyStateStructure) GetSenderChainKey() *SenderKeyStateStructure_SenderChainKey {
+ if x != nil {
+ return x.SenderChainKey
+ }
+ return nil
+}
+
+func (x *SenderKeyStateStructure) GetSenderSigningKey() *SenderKeyStateStructure_SenderSigningKey {
+ if x != nil {
+ return x.SenderSigningKey
+ }
+ return nil
+}
+
+func (x *SenderKeyStateStructure) GetSenderMessageKeys() []*SenderKeyStateStructure_SenderMessageKey {
+ if x != nil {
+ return x.SenderMessageKeys
+ }
+ return nil
+}
+
+type SenderKeyRecordStructure struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SenderKeyStates []*SenderKeyStateStructure `protobuf:"bytes,1,rep,name=senderKeyStates" json:"senderKeyStates,omitempty"`
+}
+
+func (x *SenderKeyRecordStructure) Reset() {
+ *x = SenderKeyRecordStructure{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SenderKeyRecordStructure) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SenderKeyRecordStructure) ProtoMessage() {}
+
+func (x *SenderKeyRecordStructure) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[6]
+ 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 SenderKeyRecordStructure.ProtoReflect.Descriptor instead.
+func (*SenderKeyRecordStructure) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *SenderKeyRecordStructure) GetSenderKeyStates() []*SenderKeyStateStructure {
+ if x != nil {
+ return x.SenderKeyStates
+ }
+ return nil
+}
+
+type SessionStructure_Chain struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ SenderRatchetKey []byte `protobuf:"bytes,1,opt,name=senderRatchetKey" json:"senderRatchetKey,omitempty"`
+ SenderRatchetKeyPrivate []byte `protobuf:"bytes,2,opt,name=senderRatchetKeyPrivate" json:"senderRatchetKeyPrivate,omitempty"`
+ ChainKey *SessionStructure_Chain_ChainKey `protobuf:"bytes,3,opt,name=chainKey" json:"chainKey,omitempty"`
+ MessageKeys []*SessionStructure_Chain_MessageKey `protobuf:"bytes,4,rep,name=messageKeys" json:"messageKeys,omitempty"`
+}
+
+func (x *SessionStructure_Chain) Reset() {
+ *x = SessionStructure_Chain{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[7]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure_Chain) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure_Chain) ProtoMessage() {}
+
+func (x *SessionStructure_Chain) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[7]
+ 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 SessionStructure_Chain.ProtoReflect.Descriptor instead.
+func (*SessionStructure_Chain) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *SessionStructure_Chain) GetSenderRatchetKey() []byte {
+ if x != nil {
+ return x.SenderRatchetKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_Chain) GetSenderRatchetKeyPrivate() []byte {
+ if x != nil {
+ return x.SenderRatchetKeyPrivate
+ }
+ return nil
+}
+
+func (x *SessionStructure_Chain) GetChainKey() *SessionStructure_Chain_ChainKey {
+ if x != nil {
+ return x.ChainKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_Chain) GetMessageKeys() []*SessionStructure_Chain_MessageKey {
+ if x != nil {
+ return x.MessageKeys
+ }
+ return nil
+}
+
+type SessionStructure_PendingKeyExchange struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Sequence *uint32 `protobuf:"varint,1,opt,name=sequence" json:"sequence,omitempty"`
+ LocalBaseKey []byte `protobuf:"bytes,2,opt,name=localBaseKey" json:"localBaseKey,omitempty"`
+ LocalBaseKeyPrivate []byte `protobuf:"bytes,3,opt,name=localBaseKeyPrivate" json:"localBaseKeyPrivate,omitempty"`
+ LocalRatchetKey []byte `protobuf:"bytes,4,opt,name=localRatchetKey" json:"localRatchetKey,omitempty"`
+ LocalRatchetKeyPrivate []byte `protobuf:"bytes,5,opt,name=localRatchetKeyPrivate" json:"localRatchetKeyPrivate,omitempty"`
+ LocalIdentityKey []byte `protobuf:"bytes,7,opt,name=localIdentityKey" json:"localIdentityKey,omitempty"`
+ LocalIdentityKeyPrivate []byte `protobuf:"bytes,8,opt,name=localIdentityKeyPrivate" json:"localIdentityKeyPrivate,omitempty"`
+}
+
+func (x *SessionStructure_PendingKeyExchange) Reset() {
+ *x = SessionStructure_PendingKeyExchange{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[8]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure_PendingKeyExchange) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure_PendingKeyExchange) ProtoMessage() {}
+
+func (x *SessionStructure_PendingKeyExchange) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[8]
+ 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 SessionStructure_PendingKeyExchange.ProtoReflect.Descriptor instead.
+func (*SessionStructure_PendingKeyExchange) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0, 1}
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetSequence() uint32 {
+ if x != nil && x.Sequence != nil {
+ return *x.Sequence
+ }
+ return 0
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalBaseKey() []byte {
+ if x != nil {
+ return x.LocalBaseKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalBaseKeyPrivate() []byte {
+ if x != nil {
+ return x.LocalBaseKeyPrivate
+ }
+ return nil
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalRatchetKey() []byte {
+ if x != nil {
+ return x.LocalRatchetKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalRatchetKeyPrivate() []byte {
+ if x != nil {
+ return x.LocalRatchetKeyPrivate
+ }
+ return nil
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalIdentityKey() []byte {
+ if x != nil {
+ return x.LocalIdentityKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_PendingKeyExchange) GetLocalIdentityKeyPrivate() []byte {
+ if x != nil {
+ return x.LocalIdentityKeyPrivate
+ }
+ return nil
+}
+
+type SessionStructure_PendingPreKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ PreKeyId *uint32 `protobuf:"varint,1,opt,name=preKeyId" json:"preKeyId,omitempty"`
+ SignedPreKeyId *int32 `protobuf:"varint,3,opt,name=signedPreKeyId" json:"signedPreKeyId,omitempty"`
+ BaseKey []byte `protobuf:"bytes,2,opt,name=baseKey" json:"baseKey,omitempty"`
+}
+
+func (x *SessionStructure_PendingPreKey) Reset() {
+ *x = SessionStructure_PendingPreKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[9]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure_PendingPreKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure_PendingPreKey) ProtoMessage() {}
+
+func (x *SessionStructure_PendingPreKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[9]
+ 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 SessionStructure_PendingPreKey.ProtoReflect.Descriptor instead.
+func (*SessionStructure_PendingPreKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0, 2}
+}
+
+func (x *SessionStructure_PendingPreKey) GetPreKeyId() uint32 {
+ if x != nil && x.PreKeyId != nil {
+ return *x.PreKeyId
+ }
+ return 0
+}
+
+func (x *SessionStructure_PendingPreKey) GetSignedPreKeyId() int32 {
+ if x != nil && x.SignedPreKeyId != nil {
+ return *x.SignedPreKeyId
+ }
+ return 0
+}
+
+func (x *SessionStructure_PendingPreKey) GetBaseKey() []byte {
+ if x != nil {
+ return x.BaseKey
+ }
+ return nil
+}
+
+type SessionStructure_Chain_ChainKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Index *uint32 `protobuf:"varint,1,opt,name=index" json:"index,omitempty"`
+ Key []byte `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
+}
+
+func (x *SessionStructure_Chain_ChainKey) Reset() {
+ *x = SessionStructure_Chain_ChainKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[10]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure_Chain_ChainKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure_Chain_ChainKey) ProtoMessage() {}
+
+func (x *SessionStructure_Chain_ChainKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[10]
+ 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 SessionStructure_Chain_ChainKey.ProtoReflect.Descriptor instead.
+func (*SessionStructure_Chain_ChainKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0, 0, 0}
+}
+
+func (x *SessionStructure_Chain_ChainKey) GetIndex() uint32 {
+ if x != nil && x.Index != nil {
+ return *x.Index
+ }
+ return 0
+}
+
+func (x *SessionStructure_Chain_ChainKey) GetKey() []byte {
+ if x != nil {
+ return x.Key
+ }
+ return nil
+}
+
+type SessionStructure_Chain_MessageKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Index *uint32 `protobuf:"varint,1,opt,name=index" json:"index,omitempty"`
+ CipherKey []byte `protobuf:"bytes,2,opt,name=cipherKey" json:"cipherKey,omitempty"`
+ MacKey []byte `protobuf:"bytes,3,opt,name=macKey" json:"macKey,omitempty"`
+ Iv []byte `protobuf:"bytes,4,opt,name=iv" json:"iv,omitempty"`
+}
+
+func (x *SessionStructure_Chain_MessageKey) Reset() {
+ *x = SessionStructure_Chain_MessageKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SessionStructure_Chain_MessageKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SessionStructure_Chain_MessageKey) ProtoMessage() {}
+
+func (x *SessionStructure_Chain_MessageKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[11]
+ 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 SessionStructure_Chain_MessageKey.ProtoReflect.Descriptor instead.
+func (*SessionStructure_Chain_MessageKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{0, 0, 1}
+}
+
+func (x *SessionStructure_Chain_MessageKey) GetIndex() uint32 {
+ if x != nil && x.Index != nil {
+ return *x.Index
+ }
+ return 0
+}
+
+func (x *SessionStructure_Chain_MessageKey) GetCipherKey() []byte {
+ if x != nil {
+ return x.CipherKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_Chain_MessageKey) GetMacKey() []byte {
+ if x != nil {
+ return x.MacKey
+ }
+ return nil
+}
+
+func (x *SessionStructure_Chain_MessageKey) GetIv() []byte {
+ if x != nil {
+ return x.Iv
+ }
+ return nil
+}
+
+type SenderKeyStateStructure_SenderChainKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Iteration *uint32 `protobuf:"varint,1,opt,name=iteration" json:"iteration,omitempty"`
+ Seed []byte `protobuf:"bytes,2,opt,name=seed" json:"seed,omitempty"`
+}
+
+func (x *SenderKeyStateStructure_SenderChainKey) Reset() {
+ *x = SenderKeyStateStructure_SenderChainKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SenderKeyStateStructure_SenderChainKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SenderKeyStateStructure_SenderChainKey) ProtoMessage() {}
+
+func (x *SenderKeyStateStructure_SenderChainKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[12]
+ 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 SenderKeyStateStructure_SenderChainKey.ProtoReflect.Descriptor instead.
+func (*SenderKeyStateStructure_SenderChainKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{5, 0}
+}
+
+func (x *SenderKeyStateStructure_SenderChainKey) GetIteration() uint32 {
+ if x != nil && x.Iteration != nil {
+ return *x.Iteration
+ }
+ return 0
+}
+
+func (x *SenderKeyStateStructure_SenderChainKey) GetSeed() []byte {
+ if x != nil {
+ return x.Seed
+ }
+ return nil
+}
+
+type SenderKeyStateStructure_SenderMessageKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Iteration *uint32 `protobuf:"varint,1,opt,name=iteration" json:"iteration,omitempty"`
+ Seed []byte `protobuf:"bytes,2,opt,name=seed" json:"seed,omitempty"`
+}
+
+func (x *SenderKeyStateStructure_SenderMessageKey) Reset() {
+ *x = SenderKeyStateStructure_SenderMessageKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[13]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SenderKeyStateStructure_SenderMessageKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SenderKeyStateStructure_SenderMessageKey) ProtoMessage() {}
+
+func (x *SenderKeyStateStructure_SenderMessageKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[13]
+ 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 SenderKeyStateStructure_SenderMessageKey.ProtoReflect.Descriptor instead.
+func (*SenderKeyStateStructure_SenderMessageKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{5, 1}
+}
+
+func (x *SenderKeyStateStructure_SenderMessageKey) GetIteration() uint32 {
+ if x != nil && x.Iteration != nil {
+ return *x.Iteration
+ }
+ return 0
+}
+
+func (x *SenderKeyStateStructure_SenderMessageKey) GetSeed() []byte {
+ if x != nil {
+ return x.Seed
+ }
+ return nil
+}
+
+type SenderKeyStateStructure_SenderSigningKey struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Public []byte `protobuf:"bytes,1,opt,name=public" json:"public,omitempty"`
+ Private []byte `protobuf:"bytes,2,opt,name=private" json:"private,omitempty"`
+}
+
+func (x *SenderKeyStateStructure_SenderSigningKey) Reset() {
+ *x = SenderKeyStateStructure_SenderSigningKey{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[14]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *SenderKeyStateStructure_SenderSigningKey) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SenderKeyStateStructure_SenderSigningKey) ProtoMessage() {}
+
+func (x *SenderKeyStateStructure_SenderSigningKey) ProtoReflect() protoreflect.Message {
+ mi := &file_serialize_LocalStorageProtocol_proto_msgTypes[14]
+ 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 SenderKeyStateStructure_SenderSigningKey.ProtoReflect.Descriptor instead.
+func (*SenderKeyStateStructure_SenderSigningKey) Descriptor() ([]byte, []int) {
+ return file_serialize_LocalStorageProtocol_proto_rawDescGZIP(), []int{5, 2}
+}
+
+func (x *SenderKeyStateStructure_SenderSigningKey) GetPublic() []byte {
+ if x != nil {
+ return x.Public
+ }
+ return nil
+}
+
+func (x *SenderKeyStateStructure_SenderSigningKey) GetPrivate() []byte {
+ if x != nil {
+ return x.Private
+ }
+ return nil
+}
+
+var File_serialize_LocalStorageProtocol_proto protoreflect.FileDescriptor
+
+var file_serialize_LocalStorageProtocol_proto_rawDesc = []byte{
+ 0x0a, 0x24, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x2f, 0x4c, 0x6f, 0x63, 0x61,
+ 0x6c, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 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, 0xbf, 0x0c, 0x0a, 0x10, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74,
+ 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x73, 0x73, 0x69,
+ 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x0e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12,
+ 0x30, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
+ 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69,
+ 0x63, 0x12, 0x32, 0x0a, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74,
+ 0x69, 0x74, 0x79, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
+ 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x50,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x4b, 0x65, 0x79, 0x12,
+ 0x28, 0x0a, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f,
+ 0x75, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x0b, 0x73, 0x65, 0x6e,
+ 0x64, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22,
+ 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73,
+ 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61,
+ 0x69, 0x6e, 0x52, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12,
+ 0x4a, 0x0a, 0x0e, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e,
+ 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65,
+ 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x0e, 0x72, 0x65, 0x63,
+ 0x65, 0x69, 0x76, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x5f, 0x0a, 0x12, 0x70,
+ 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65,
+ 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79,
+ 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x12, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e,
+ 0x67, 0x4b, 0x65, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x50, 0x0a, 0x0d,
+ 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x09, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65,
+ 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72,
+ 0x65, 0x2e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x52,
+ 0x0d, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x32,
+ 0x0a, 0x14, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65,
+ 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
+ 0x49, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x67, 0x69, 0x73,
+ 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65, 0x66,
+ 0x72, 0x65, 0x73, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x65, 0x65, 0x64,
+ 0x73, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x61, 0x6c, 0x69, 0x63,
+ 0x65, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c,
+ 0x61, 0x6c, 0x69, 0x63, 0x65, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x1a, 0xa5, 0x03, 0x0a,
+ 0x05, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x2a, 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72,
+ 0x52, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
+ 0x52, 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b,
+ 0x65, 0x79, 0x12, 0x38, 0x0a, 0x17, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x61, 0x74, 0x63,
+ 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0c, 0x52, 0x17, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x61, 0x74, 0x63, 0x68,
+ 0x65, 0x74, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x47, 0x0a, 0x08,
+ 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b,
+ 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73,
+ 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61,
+ 0x69, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x08, 0x63, 0x68, 0x61,
+ 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x4f, 0x0a, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x4b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x78,
+ 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53,
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x2e, 0x4d,
+ 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61,
+ 0x67, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x32, 0x0a, 0x08, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b,
+ 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x1a, 0x68, 0x0a, 0x0a, 0x4d, 0x65,
+ 0x73, 0x73, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c,
+ 0x0a, 0x09, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x09, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06,
+ 0x6d, 0x61, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x6d, 0x61,
+ 0x63, 0x4b, 0x65, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
+ 0x52, 0x02, 0x69, 0x76, 0x1a, 0xce, 0x02, 0x0a, 0x12, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x4b, 0x65, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73,
+ 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73,
+ 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x6c,
+ 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x6c,
+ 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61,
+ 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x42,
+ 0x61, 0x73, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a,
+ 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79,
+ 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x61, 0x74,
+ 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x52, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x52, 0x61,
+ 0x74, 0x63, 0x68, 0x65, 0x74, 0x4b, 0x65, 0x79, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x12,
+ 0x2a, 0x0a, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
+ 0x4b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x10, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x17, 0x6c,
+ 0x6f, 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x50,
+ 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x17, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x50, 0x72,
+ 0x69, 0x76, 0x61, 0x74, 0x65, 0x1a, 0x6d, 0x0a, 0x0d, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67,
+ 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79, 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, 0x03, 0x20, 0x01, 0x28, 0x05, 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, 0x22, 0xa1, 0x01, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53,
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x63, 0x75, 0x72, 0x72,
+ 0x65, 0x6e, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+ 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65,
+ 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0e,
+ 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x48,
+ 0x0a, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72,
+ 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x10, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73,
+ 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x65, 0x0a, 0x15, 0x50, 0x72, 0x65, 0x4b,
+ 0x65, 0x79, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72,
+ 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69,
+ 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12,
+ 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x22,
+ 0xa7, 0x01, 0x0a, 0x1b, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x50, 0x72, 0x65, 0x4b, 0x65, 0x79,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12,
+ 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
+ 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a,
+ 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a,
+ 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
+ 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74,
+ 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x06, 0x52, 0x09,
+ 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x58, 0x0a, 0x18, 0x49, 0x64, 0x65,
+ 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x69, 0x72, 0x53, 0x74, 0x72, 0x75,
+ 0x63, 0x74, 0x75, 0x72, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b,
+ 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
+ 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65,
+ 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
+ 0x4b, 0x65, 0x79, 0x22, 0xad, 0x04, 0x0a, 0x17, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65,
+ 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12,
+ 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x49,
+ 0x64, 0x12, 0x5a, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e,
+ 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x78, 0x74,
+ 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x53,
+ 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x0e, 0x73,
+ 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x60, 0x0a,
+ 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65,
+ 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x65,
+ 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x6e,
+ 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x52, 0x10, 0x73,
+ 0x65, 0x6e, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12,
+ 0x62, 0x0a, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x4b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x74, 0x65, 0x78,
+ 0x74, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65,
+ 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2e,
+ 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79,
+ 0x52, 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4b,
+ 0x65, 0x79, 0x73, 0x1a, 0x42, 0x0a, 0x0e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x68, 0x61,
+ 0x69, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69,
+ 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x1a, 0x44, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x65,
+ 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x69,
+ 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09,
+ 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65,
+ 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x1a, 0x44, 0x0a,
+ 0x10, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65,
+ 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0c, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x69,
+ 0x76, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x72, 0x69, 0x76,
+ 0x61, 0x74, 0x65, 0x22, 0x69, 0x0a, 0x18, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79,
+ 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x12,
+ 0x4d, 0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x73,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53,
+ 0x74, 0x61, 0x74, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x52, 0x0f, 0x73,
+ 0x65, 0x6e, 0x64, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x42, 0x33,
+ 0x0a, 0x22, 0x6f, 0x72, 0x67, 0x2e, 0x77, 0x68, 0x69, 0x73, 0x70, 0x65, 0x72, 0x73, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x2e, 0x73,
+ 0x74, 0x61, 0x74, 0x65, 0x42, 0x0d, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f,
+ 0x74, 0x6f, 0x73,
+}
+
+var (
+ file_serialize_LocalStorageProtocol_proto_rawDescOnce sync.Once
+ file_serialize_LocalStorageProtocol_proto_rawDescData = file_serialize_LocalStorageProtocol_proto_rawDesc
+)
+
+func file_serialize_LocalStorageProtocol_proto_rawDescGZIP() []byte {
+ file_serialize_LocalStorageProtocol_proto_rawDescOnce.Do(func() {
+ file_serialize_LocalStorageProtocol_proto_rawDescData = protoimpl.X.CompressGZIP(file_serialize_LocalStorageProtocol_proto_rawDescData)
+ })
+ return file_serialize_LocalStorageProtocol_proto_rawDescData
+}
+
+var file_serialize_LocalStorageProtocol_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
+var file_serialize_LocalStorageProtocol_proto_goTypes = []interface{}{
+ (*SessionStructure)(nil), // 0: textsecure.SessionStructure
+ (*RecordStructure)(nil), // 1: textsecure.RecordStructure
+ (*PreKeyRecordStructure)(nil), // 2: textsecure.PreKeyRecordStructure
+ (*SignedPreKeyRecordStructure)(nil), // 3: textsecure.SignedPreKeyRecordStructure
+ (*IdentityKeyPairStructure)(nil), // 4: textsecure.IdentityKeyPairStructure
+ (*SenderKeyStateStructure)(nil), // 5: textsecure.SenderKeyStateStructure
+ (*SenderKeyRecordStructure)(nil), // 6: textsecure.SenderKeyRecordStructure
+ (*SessionStructure_Chain)(nil), // 7: textsecure.SessionStructure.Chain
+ (*SessionStructure_PendingKeyExchange)(nil), // 8: textsecure.SessionStructure.PendingKeyExchange
+ (*SessionStructure_PendingPreKey)(nil), // 9: textsecure.SessionStructure.PendingPreKey
+ (*SessionStructure_Chain_ChainKey)(nil), // 10: textsecure.SessionStructure.Chain.ChainKey
+ (*SessionStructure_Chain_MessageKey)(nil), // 11: textsecure.SessionStructure.Chain.MessageKey
+ (*SenderKeyStateStructure_SenderChainKey)(nil), // 12: textsecure.SenderKeyStateStructure.SenderChainKey
+ (*SenderKeyStateStructure_SenderMessageKey)(nil), // 13: textsecure.SenderKeyStateStructure.SenderMessageKey
+ (*SenderKeyStateStructure_SenderSigningKey)(nil), // 14: textsecure.SenderKeyStateStructure.SenderSigningKey
+}
+var file_serialize_LocalStorageProtocol_proto_depIdxs = []int32{
+ 7, // 0: textsecure.SessionStructure.senderChain:type_name -> textsecure.SessionStructure.Chain
+ 7, // 1: textsecure.SessionStructure.receiverChains:type_name -> textsecure.SessionStructure.Chain
+ 8, // 2: textsecure.SessionStructure.pendingKeyExchange:type_name -> textsecure.SessionStructure.PendingKeyExchange
+ 9, // 3: textsecure.SessionStructure.pendingPreKey:type_name -> textsecure.SessionStructure.PendingPreKey
+ 0, // 4: textsecure.RecordStructure.currentSession:type_name -> textsecure.SessionStructure
+ 0, // 5: textsecure.RecordStructure.previousSessions:type_name -> textsecure.SessionStructure
+ 12, // 6: textsecure.SenderKeyStateStructure.senderChainKey:type_name -> textsecure.SenderKeyStateStructure.SenderChainKey
+ 14, // 7: textsecure.SenderKeyStateStructure.senderSigningKey:type_name -> textsecure.SenderKeyStateStructure.SenderSigningKey
+ 13, // 8: textsecure.SenderKeyStateStructure.senderMessageKeys:type_name -> textsecure.SenderKeyStateStructure.SenderMessageKey
+ 5, // 9: textsecure.SenderKeyRecordStructure.senderKeyStates:type_name -> textsecure.SenderKeyStateStructure
+ 10, // 10: textsecure.SessionStructure.Chain.chainKey:type_name -> textsecure.SessionStructure.Chain.ChainKey
+ 11, // 11: textsecure.SessionStructure.Chain.messageKeys:type_name -> textsecure.SessionStructure.Chain.MessageKey
+ 12, // [12:12] is the sub-list for method output_type
+ 12, // [12:12] is the sub-list for method input_type
+ 12, // [12:12] is the sub-list for extension type_name
+ 12, // [12:12] is the sub-list for extension extendee
+ 0, // [0:12] is the sub-list for field type_name
+}
+
+func init() { file_serialize_LocalStorageProtocol_proto_init() }
+func file_serialize_LocalStorageProtocol_proto_init() {
+ if File_serialize_LocalStorageProtocol_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_serialize_LocalStorageProtocol_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RecordStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*PreKeyRecordStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SignedPreKeyRecordStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*IdentityKeyPairStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SenderKeyStateStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SenderKeyRecordStructure); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure_Chain); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure_PendingKeyExchange); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure_PendingPreKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure_Chain_ChainKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SessionStructure_Chain_MessageKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SenderKeyStateStructure_SenderChainKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SenderKeyStateStructure_SenderMessageKey); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_serialize_LocalStorageProtocol_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*SenderKeyStateStructure_SenderSigningKey); 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_LocalStorageProtocol_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 15,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_serialize_LocalStorageProtocol_proto_goTypes,
+ DependencyIndexes: file_serialize_LocalStorageProtocol_proto_depIdxs,
+ MessageInfos: file_serialize_LocalStorageProtocol_proto_msgTypes,
+ }.Build()
+ File_serialize_LocalStorageProtocol_proto = out.File
+ file_serialize_LocalStorageProtocol_proto_rawDesc = nil
+ file_serialize_LocalStorageProtocol_proto_goTypes = nil
+ file_serialize_LocalStorageProtocol_proto_depIdxs = nil
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto b/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto
new file mode 100644
index 00000000..8ae9c01a
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto
@@ -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;
+} \ No newline at end of file
diff --git a/vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go b/vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go
new file mode 100644
index 00000000..81482d31
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/Serializer.go b/vendor/go.mau.fi/libsignal/serialize/Serializer.go
new file mode 100644
index 00000000..fe7dd433
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/Serializer.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go b/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go
new file mode 100644
index 00000000..18143be5
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto b/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto
new file mode 100644
index 00000000..def080b4
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto
@@ -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;
+} \ No newline at end of file
diff --git a/vendor/go.mau.fi/libsignal/session/Session.go b/vendor/go.mau.fi/libsignal/session/Session.go
new file mode 100644
index 00000000..aafac760
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/session/Session.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/session/SessionCipher.go b/vendor/go.mau.fi/libsignal/session/SessionCipher.go
new file mode 100644
index 00000000..a70812b9
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/session/SessionCipher.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/signalerror/errors.go b/vendor/go.mau.fi/libsignal/signalerror/errors.go
new file mode 100644
index 00000000..51232160
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/signalerror/errors.go
@@ -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")
diff --git a/vendor/go.mau.fi/libsignal/state/record/ChainState.go b/vendor/go.mau.fi/libsignal/state/record/ChainState.go
new file mode 100644
index 00000000..dd07bf89
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/ChainState.go
@@ -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,
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/Doc.go b/vendor/go.mau.fi/libsignal/state/record/Doc.go
new file mode 100644
index 00000000..036419da
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/Doc.go
@@ -0,0 +1,3 @@
+// Package record provides the state and record of an ongoing double
+// ratchet session.
+package record
diff --git a/vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go b/vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
new file mode 100644
index 00000000..ac647215
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go
@@ -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()),
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go b/vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
new file mode 100644
index 00000000..27a8878b
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go b/vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
new file mode 100644
index 00000000..dcd630d2
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/SessionRecord.go b/vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
new file mode 100644
index 00000000..01e817e4
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/SessionRecord.go
@@ -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,
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/SessionState.go b/vendor/go.mau.fi/libsignal/state/record/SessionState.go
new file mode 100644
index 00000000..d0f61d5c
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/SessionState.go
@@ -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,
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go b/vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
new file mode 100644
index 00000000..f11ab088
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go b/vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
new file mode 100644
index 00000000..61fe0644
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go
@@ -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(),
+ }
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/Doc.go b/vendor/go.mau.fi/libsignal/state/store/Doc.go
new file mode 100644
index 00000000..9a018d3d
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/Doc.go
@@ -0,0 +1,3 @@
+// Package store provides the storage interfaces for storing the state of
+// ongoing double ratchet sessions and keys.
+package store
diff --git a/vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go b/vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go
new file mode 100644
index 00000000..05ad8d1e
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go b/vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go
new file mode 100644
index 00000000..fea2eed0
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go b/vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go
new file mode 100644
index 00000000..a132be65
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/SessionStore.go b/vendor/go.mau.fi/libsignal/state/store/SessionStore.go
new file mode 100644
index 00000000..e18fc024
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/SessionStore.go
@@ -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()
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go b/vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go
new file mode 100644
index 00000000..081e0380
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go b/vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go
new file mode 100644
index 00000000..058cd670
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go
@@ -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)
+}
diff --git a/vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go b/vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go
new file mode 100644
index 00000000..78f71ae4
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go
@@ -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
+}
diff --git a/vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go b/vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go
new file mode 100644
index 00000000..b30adb0a
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go
@@ -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()
+}
diff --git a/vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go b/vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go
new file mode 100644
index 00000000..62481cc1
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go
@@ -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 --------------
diff --git a/vendor/go.mau.fi/libsignal/util/medium/Medium.go b/vendor/go.mau.fi/libsignal/util/medium/Medium.go
new file mode 100644
index 00000000..7a509a8e
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/util/medium/Medium.go
@@ -0,0 +1,4 @@
+package medium
+
+// MaxValue is the maximum possible integer value.
+const MaxValue uint32 = 0xFFFFFF
diff --git a/vendor/go.mau.fi/libsignal/util/optional/Integer.go b/vendor/go.mau.fi/libsignal/util/optional/Integer.go
new file mode 100644
index 00000000..9e43af46
--- /dev/null
+++ b/vendor/go.mau.fi/libsignal/util/optional/Integer.go
@@ -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
+}