From e3cafeaf9292f67459ff1d186f68283bfaedf2ae Mon Sep 17 00:00:00 2001 From: Wim Date: Mon, 31 Jan 2022 00:27:37 +0100 Subject: Add dependencies/vendor (whatsapp) --- vendor/go.mau.fi/libsignal/LICENSE | 674 +++++++++ vendor/go.mau.fi/libsignal/cipher/Cbc.go | 101 ++ vendor/go.mau.fi/libsignal/cipher/Cipher.go | 105 ++ vendor/go.mau.fi/libsignal/ecc/Curve.go | 109 ++ vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go | 29 + vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go | 29 + vendor/go.mau.fi/libsignal/ecc/Doc.go | 3 + vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go | 27 + vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go | 7 + vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go | 11 + vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go | 97 ++ vendor/go.mau.fi/libsignal/groups/GroupCipher.go | 141 ++ .../libsignal/groups/GroupSessionBuilder.go | 84 ++ vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go | 3 + .../libsignal/groups/ratchet/SenderChainKey.go | 68 + .../libsignal/groups/ratchet/SenderMessageKey.go | 89 ++ .../go.mau.fi/libsignal/groups/state/record/Doc.go | 2 + .../groups/state/record/SenderKeyRecord.go | 149 ++ .../groups/state/record/SenderKeyState.go | 186 +++ .../go.mau.fi/libsignal/groups/state/store/Doc.go | 3 + .../libsignal/groups/state/store/SenderKeyStore.go | 11 + vendor/go.mau.fi/libsignal/kdf/HKDF.go | 47 + vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go | 127 ++ .../libsignal/keys/identity/IdentityKey.go | 47 + .../libsignal/keys/identity/IdentityKeyPair.go | 39 + .../go.mau.fi/libsignal/keys/message/MessageKey.go | 91 ++ .../libsignal/keys/prekey/PreKeyBundle.go | 86 ++ vendor/go.mau.fi/libsignal/keys/root/RootKey.go | 66 + .../libsignal/keys/session/DerivedSecrets.go | 29 + vendor/go.mau.fi/libsignal/keys/session/Pair.go | 43 + vendor/go.mau.fi/libsignal/logger/DefaultLogger.go | 85 ++ vendor/go.mau.fi/libsignal/logger/Logger.go | 89 ++ .../libsignal/protocol/CiphertextMessage.go | 19 + vendor/go.mau.fi/libsignal/protocol/Doc.go | 3 + .../libsignal/protocol/PreKeySignalMessage.go | 152 ++ .../protocol/SenderKeyDistributionMessage.go | 147 ++ .../libsignal/protocol/SenderKeyMessage.go | 168 +++ .../go.mau.fi/libsignal/protocol/SenderKeyName.go | 25 + .../go.mau.fi/libsignal/protocol/SignalMessage.go | 226 +++ .../libsignal/protocol/SignalProtocolAddress.go | 38 + vendor/go.mau.fi/libsignal/ratchet/Ratchet.go | 197 +++ .../libsignal/ratchet/ReceiverParameters.go | 106 ++ .../libsignal/ratchet/SenderParameters.go | 106 ++ .../libsignal/ratchet/SymmetricParameters.go | 18 + .../libsignal/serialize/FingerprintProtocol.pb.go | 245 ++++ .../libsignal/serialize/FingerprintProtocol.proto | 14 + .../libsignal/serialize/JSONSerializer.go | 303 ++++ .../libsignal/serialize/LocalStorageProtocol.pb.go | 1500 ++++++++++++++++++++ .../libsignal/serialize/LocalStorageProtocol.proto | 114 ++ .../libsignal/serialize/ProtoBufferSerializer.go | 262 ++++ vendor/go.mau.fi/libsignal/serialize/Serializer.go | 31 + .../libsignal/serialize/WhisperTextProtocol.pb.go | 640 +++++++++ .../libsignal/serialize/WhisperTextProtocol.proto | 45 + vendor/go.mau.fi/libsignal/session/Session.go | 272 ++++ .../go.mau.fi/libsignal/session/SessionCipher.go | 366 +++++ vendor/go.mau.fi/libsignal/signalerror/errors.go | 37 + .../go.mau.fi/libsignal/state/record/ChainState.go | 157 ++ vendor/go.mau.fi/libsignal/state/record/Doc.go | 3 + .../state/record/PendingKeyExchangeState.go | 91 ++ .../libsignal/state/record/PendingPreKeyState.go | 62 + .../libsignal/state/record/PreKeyRecord.go | 90 ++ .../libsignal/state/record/SessionRecord.go | 197 +++ .../libsignal/state/record/SessionState.go | 531 +++++++ .../libsignal/state/record/SignedPreKeyRecord.go | 112 ++ .../libsignal/state/record/UnacknowledgedPreKey.go | 69 + vendor/go.mau.fi/libsignal/state/store/Doc.go | 3 + .../libsignal/state/store/IdentityKeyStore.go | 29 + .../libsignal/state/store/MessageKeyStore.go | 21 + .../go.mau.fi/libsignal/state/store/PreKeyStore.go | 21 + .../libsignal/state/store/SessionStore.go | 17 + .../libsignal/state/store/SignalProtocolStore.go | 15 + .../libsignal/state/store/SignedPreKeyStore.go | 24 + .../libsignal/util/bytehelper/ByteHelper.go | 97 ++ .../libsignal/util/errorhelper/ErrorHelper.go | 40 + .../libsignal/util/keyhelper/KeyHelper.go | 95 ++ vendor/go.mau.fi/libsignal/util/medium/Medium.go | 4 + .../go.mau.fi/libsignal/util/optional/Integer.go | 17 + 77 files changed, 9406 insertions(+) create mode 100644 vendor/go.mau.fi/libsignal/LICENSE create mode 100644 vendor/go.mau.fi/libsignal/cipher/Cbc.go create mode 100644 vendor/go.mau.fi/libsignal/cipher/Cipher.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/Curve.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/DjbECPublicKey.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/DkbECPrivateKey.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/ECKeyPair.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/ECPrivateKey.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/ECPublicKey.go create mode 100644 vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go create mode 100644 vendor/go.mau.fi/libsignal/groups/GroupCipher.go create mode 100644 vendor/go.mau.fi/libsignal/groups/GroupSessionBuilder.go create mode 100644 vendor/go.mau.fi/libsignal/groups/ratchet/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/groups/ratchet/SenderChainKey.go create mode 100644 vendor/go.mau.fi/libsignal/groups/ratchet/SenderMessageKey.go create mode 100644 vendor/go.mau.fi/libsignal/groups/state/record/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyRecord.go create mode 100644 vendor/go.mau.fi/libsignal/groups/state/record/SenderKeyState.go create mode 100644 vendor/go.mau.fi/libsignal/groups/state/store/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/groups/state/store/SenderKeyStore.go create mode 100644 vendor/go.mau.fi/libsignal/kdf/HKDF.go create mode 100644 vendor/go.mau.fi/libsignal/keys/chain/ChainKey.go create mode 100644 vendor/go.mau.fi/libsignal/keys/identity/IdentityKey.go create mode 100644 vendor/go.mau.fi/libsignal/keys/identity/IdentityKeyPair.go create mode 100644 vendor/go.mau.fi/libsignal/keys/message/MessageKey.go create mode 100644 vendor/go.mau.fi/libsignal/keys/prekey/PreKeyBundle.go create mode 100644 vendor/go.mau.fi/libsignal/keys/root/RootKey.go create mode 100644 vendor/go.mau.fi/libsignal/keys/session/DerivedSecrets.go create mode 100644 vendor/go.mau.fi/libsignal/keys/session/Pair.go create mode 100644 vendor/go.mau.fi/libsignal/logger/DefaultLogger.go create mode 100644 vendor/go.mau.fi/libsignal/logger/Logger.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/CiphertextMessage.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/PreKeySignalMessage.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/SenderKeyDistributionMessage.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/SenderKeyMessage.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/SenderKeyName.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/SignalMessage.go create mode 100644 vendor/go.mau.fi/libsignal/protocol/SignalProtocolAddress.go create mode 100644 vendor/go.mau.fi/libsignal/ratchet/Ratchet.go create mode 100644 vendor/go.mau.fi/libsignal/ratchet/ReceiverParameters.go create mode 100644 vendor/go.mau.fi/libsignal/ratchet/SenderParameters.go create mode 100644 vendor/go.mau.fi/libsignal/ratchet/SymmetricParameters.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.pb.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/FingerprintProtocol.proto create mode 100644 vendor/go.mau.fi/libsignal/serialize/JSONSerializer.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.pb.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/LocalStorageProtocol.proto create mode 100644 vendor/go.mau.fi/libsignal/serialize/ProtoBufferSerializer.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/Serializer.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.pb.go create mode 100644 vendor/go.mau.fi/libsignal/serialize/WhisperTextProtocol.proto create mode 100644 vendor/go.mau.fi/libsignal/session/Session.go create mode 100644 vendor/go.mau.fi/libsignal/session/SessionCipher.go create mode 100644 vendor/go.mau.fi/libsignal/signalerror/errors.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/ChainState.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/PendingKeyExchangeState.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/PendingPreKeyState.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/PreKeyRecord.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/SessionRecord.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/SessionState.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/SignedPreKeyRecord.go create mode 100644 vendor/go.mau.fi/libsignal/state/record/UnacknowledgedPreKey.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/Doc.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/IdentityKeyStore.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/MessageKeyStore.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/PreKeyStore.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/SessionStore.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/SignalProtocolStore.go create mode 100644 vendor/go.mau.fi/libsignal/state/store/SignedPreKeyStore.go create mode 100644 vendor/go.mau.fi/libsignal/util/bytehelper/ByteHelper.go create mode 100644 vendor/go.mau.fi/libsignal/util/errorhelper/ErrorHelper.go create mode 100644 vendor/go.mau.fi/libsignal/util/keyhelper/KeyHelper.go create mode 100644 vendor/go.mau.fi/libsignal/util/medium/Medium.go create mode 100644 vendor/go.mau.fi/libsignal/util/optional/Integer.go (limited to 'vendor/go.mau.fi/libsignal') 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. + 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 . + +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 +. + + 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 +. 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 = "" + } + + 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 +} -- cgit v1.2.3