Full Code of tgalal/python-axolotl for AI

master b8d1a2e04bda cached
99 files
261.3 KB
67.9k tokens
511 symbols
1 requests
Download .txt
Showing preview only (286K chars total). Download the full file or copy to clipboard to get everything.
Repository: tgalal/python-axolotl
Branch: master
Commit: b8d1a2e04bda
Files: 99
Total size: 261.3 KB

Directory structure:
gitextract_vf0yghin/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── axolotl/
│   ├── __init__.py
│   ├── axolotladdress.py
│   ├── duplicatemessagexception.py
│   ├── ecc/
│   │   ├── __init__.py
│   │   ├── curve.py
│   │   ├── djbec.py
│   │   ├── ec.py
│   │   └── eckeypair.py
│   ├── groups/
│   │   ├── __init__.py
│   │   ├── groupcipher.py
│   │   ├── groupsessionbuilder.py
│   │   ├── ratchet/
│   │   │   ├── __init__.py
│   │   │   ├── senderchainkey.py
│   │   │   └── sendermessagekey.py
│   │   ├── senderkeyname.py
│   │   └── state/
│   │       ├── __init__.py
│   │       ├── senderkeyrecord.py
│   │       ├── senderkeystate.py
│   │       └── senderkeystore.py
│   ├── identitykey.py
│   ├── identitykeypair.py
│   ├── invalidkeyexception.py
│   ├── invalidkeyidexception.py
│   ├── invalidmessageexception.py
│   ├── invalidversionexception.py
│   ├── kdf/
│   │   ├── __init__.py
│   │   ├── derivedmessagesecrets.py
│   │   ├── derivedrootsecrets.py
│   │   ├── hkdf.py
│   │   ├── hkdfv2.py
│   │   ├── hkdfv3.py
│   │   └── messagekeys.py
│   ├── legacymessageexception.py
│   ├── nosessionexception.py
│   ├── protobuf/
│   │   ├── LocalStorageProtocol.proto
│   │   └── WhisperTextProtocol.proto
│   ├── protocol/
│   │   ├── __init__.py
│   │   ├── ciphertextmessage.py
│   │   ├── keyexchangemessage.py
│   │   ├── prekeywhispermessage.py
│   │   ├── senderkeydistributionmessage.py
│   │   ├── senderkeymessage.py
│   │   ├── whispermessage.py
│   │   └── whisperprotos_pb2.py
│   ├── ratchet/
│   │   ├── __init__.py
│   │   ├── aliceaxolotlparameters.py
│   │   ├── bobaxolotlparamaters.py
│   │   ├── chainkey.py
│   │   ├── ratchetingsession.py
│   │   ├── rootkey.py
│   │   └── symmetricaxolotlparameters.py
│   ├── sessionbuilder.py
│   ├── sessioncipher.py
│   ├── state/
│   │   ├── __init__.py
│   │   ├── axolotlstore.py
│   │   ├── identitykeystore.py
│   │   ├── prekeybundle.py
│   │   ├── prekeyrecord.py
│   │   ├── prekeystore.py
│   │   ├── sessionrecord.py
│   │   ├── sessionstate.py
│   │   ├── sessionstore.py
│   │   ├── signedprekeyrecord.py
│   │   ├── signedprekeystore.py
│   │   └── storageprotos_pb2.py
│   ├── statekeyexchangeexception.py
│   ├── tests/
│   │   ├── __init__.py
│   │   ├── groups/
│   │   │   ├── __init__.py
│   │   │   ├── inmemorysenderkeystore.py
│   │   │   └── test_groupcipher.py
│   │   ├── inmemoryaxolotlstore.py
│   │   ├── inmemoryidentitykeystore.py
│   │   ├── inmemoryprekeystore.py
│   │   ├── inmemorysessionstore.py
│   │   ├── inmemorysignedprekeystore.py
│   │   ├── kdf/
│   │   │   ├── __init__.py
│   │   │   └── test_hkdf.py
│   │   ├── ratchet/
│   │   │   ├── __init__.py
│   │   │   ├── test_chainkey.py
│   │   │   ├── test_ratchetingsession.py
│   │   │   └── test_rootkey.py
│   │   ├── test_sessionbuilder.py
│   │   ├── test_sessioncipher.py
│   │   ├── test_sigs.py
│   │   └── util/
│   │       ├── __init__.py
│   │       └── test_byteutil.py
│   ├── untrustedidentityexception.py
│   └── util/
│       ├── __init__.py
│       ├── byteutil.py
│       ├── hexutil.py
│       ├── keyhelper.py
│       └── medium.py
├── setup.py
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/FUNDING.yml
================================================
github: [tgalal]


================================================
FILE: .gitignore
================================================
# Created by https://www.gitignore.io/api/windows,linux,osx,python,vim

### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk


### Linux ###
*~

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*


### OSX ###
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover

# Translations
*.mo
*.pot

# Django stuff:
*.log

# Sphinx documentation
docs/_build/

# PyBuilder
target/


### Vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~



================================================
FILE: .travis.yml
================================================
language: python
python: '3.7'
# command to install dependencies

env:
  global:
    - LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
    - SEGFAULT_SIGNALS=all
  matrix:
    - TOXENV=py26
    - TOXENV=py27
    - TOXENV=py32
    - TOXENV=py33
    - TOXENV=py35
    - TOXENV=py36
    - TOXENV=py37
before_install:
  - python --version
  - uname -a
  - lsb_release -a
install:
  - pip install tox
  - virtualenv --version
  - easy_install --version
  - pip --version
  - tox --version
# command to run tests
script:
  - tox -v
after_failure:
  - more .tox/log/* | cat
  - more .tox/*/log/* | cat
before_cache:
  - rm -rf $HOME/.cache/pip/log
cache:
  directories:
    - $HOME/.cache/pip
branches:
  only:
    - master


================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    {one line to give the program's name and a brief idea of what it does.}
    Copyright (C) {year}  {name of author}

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    {project}  Copyright (C) {year}  {fullname}
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.



================================================
FILE: README.md
================================================
This is a python port of [libsignal-protocol-java](https://github.com/WhisperSystems/libaxolotl-android) originally written by [Moxie Marlinspike](https://github.com/moxie0)

Overview from original author's:

 > This is a ratcheting forward secrecy protocol that works in synchronous and asynchronous messaging environments.
 
# Installation

The library has some dependencies which are automatically pulled and installed if you use the instructions below for your OS

 - [protobuf 3.0+](https://github.com/google/protobuf/)
 - [cryptography](https://cryptography.io)
 - [python-axolotl-curve25519](https://github.com/tgalal/python-axolotl-curve25519)

## Linux

You need to have python headers installed, usually through installing a package called `python-dev`, then as superuser run:
```
python setup.py install
```

## Windows

 - Install [mingw](http://www.mingw.org/) compiler
 - Add mingw to your PATH
 - In PYTHONPATH\Lib\distutils create a file called distutils.cfg and add these lines:
 
```
[build]
compiler=mingw32
```

 - Install gcc: ```mingw-get.exe install gcc```
 - Install [zlib](http://www.zlib.net/)
 - ```python setup.py install```


# Usage

This python port is done in an almost 1:1 mapping to the original java code. Therefore any original documentation for the java code can be easily mapped and used with this python port.

## Install time

At install time, a libaxolotl client needs to generate its identity keys, registration id, and
prekeys.

```python
    identityKeyPair = KeyHelper.generateIdentityKeyPair()
    registrationId  = KeyHelper.generateRegistrationId()
    preKeys         = KeyHelper.generatePreKeys(startId, 100)
    lastResortKey   = KeyHelper.generateLastResortKey()
    signedPreKey    = KeyHelper.generateSignedPreKey(identityKeyPair, 5)

    #Store identityKeyPair somewhere durable and safe.
    #Store registrationId somewhere durable and safe.

    #Store preKeys in PreKeyStore.
    #Store signed prekey in SignedPreKeyStore.
```

## Building a session

A libaxolotl client needs to implement four interfaces: IdentityKeyStore, PreKeyStore, 
SignedPreKeyStore, and SessionStore.  These will manage loading and storing of identity, 
prekeys, signed prekeys, and session state.

Once those are implemented, building a session is fairly straightforward:

```python
sessionStore      = MySessionStore()
preKeyStore       = MyPreKeyStore()
signedPreKeyStore = MySignedPreKeyStore()
identityStore     = MyIdentityKeyStore()

# Instantiate a SessionBuilder for a remote recipientId + deviceId tuple.
sessionBuilder = SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
                                                   identityStore, recipientId, deviceId)

# Build a session with a PreKey retrieved from the server.
sessionBuilder.process(retrievedPreKey)

sessionCipher = SessionCipher(sessionStore, recipientId, deviceId)
message       = sessionCipher.encrypt("Hello world!")

deliver(message.serialize())
```

# Examples

python-axolotl is actively used in [yowsup](https://github.com/tgalal/yowsup) to support E2E encryption of WhatsApp

# License

Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html


================================================
FILE: axolotl/__init__.py
================================================
# -*- coding: utf-8 -*-

__version__ = '0.2.3'
__author__ = 'Tarek Galal'
__email__ = 'tare2.galal@gmail.com'
__license__ = 'GPLv3'
__status__ = 'Production'


================================================
FILE: axolotl/axolotladdress.py
================================================
class AxolotlAddress(object):
    def __init__(self, name, deviceId):
        self.name = name
        self.deviceId = deviceId

    def getName(self):
        return self.name

    def getDeviceId(self):
        return self.deviceId

    def __str__(self):
        return "%s;%s" % (self.name, self.deviceId)

    def __eq__(self, other):
        if other is None:
            return False

        if other.__class__ != AxolotlAddress:
            return False

        return self.name == other.getName() and self.deviceId == other.getDeviceId()

    def __hash__(self):
        return hash(self.name) ^ self.deviceId


================================================
FILE: axolotl/duplicatemessagexception.py
================================================
# -*- coding: utf-8 -*-


class DuplicateMessageException(Exception):
    pass


================================================
FILE: axolotl/ecc/__init__.py
================================================


================================================
FILE: axolotl/ecc/curve.py
================================================
# -*- coding: utf-8 -*-

import os

from .eckeypair import ECKeyPair
from ..invalidkeyexception import InvalidKeyException

import axolotl_curve25519 as _curve


class Curve:
    DJB_TYPE = 5
    # always DJB curve25519 keys

    @staticmethod
    def generatePrivateKey():
        rand = os.urandom(32)
        return _curve.generatePrivateKey(rand)

    @staticmethod
    def generatePublicKey(privateKey):
        return _curve.generatePublicKey(privateKey)

    @staticmethod
    def generateKeyPair():
        from .djbec import DjbECPublicKey, DjbECPrivateKey

        privateKey = Curve.generatePrivateKey()
        publicKey = Curve.generatePublicKey(privateKey)
        return ECKeyPair(DjbECPublicKey(publicKey), DjbECPrivateKey(privateKey))

    @staticmethod
    def decodePoint(_bytes, offset=0):
        type = _bytes[0]  # byte appears to be automatically converted to an integer??

        if type == Curve.DJB_TYPE:
            from .djbec import DjbECPublicKey

            type = _bytes[offset] & 0xFF
            if type != Curve.DJB_TYPE:
                raise InvalidKeyException("Unknown key type: %s " % type)
            keyBytes = _bytes[offset+1:][:32]
            return DjbECPublicKey(bytes(keyBytes))
        else:
            raise InvalidKeyException("Unknown key type: %s" % type)

    @staticmethod
    def decodePrivatePoint(_bytes):
        from .djbec import DjbECPrivateKey
        return DjbECPrivateKey(bytes(_bytes))

    @staticmethod
    def calculateAgreement(publicKey, privateKey):
        """
        :type publicKey: ECPublicKey
        :type privateKey: ECPrivateKey
        """
        if publicKey.getType() != privateKey.getType():
            raise InvalidKeyException("Public and private keys must be of the same type!")

        if publicKey.getType() == Curve.DJB_TYPE:
            return _curve.calculateAgreement(privateKey.getPrivateKey(), publicKey.getPublicKey())
        else:
            raise InvalidKeyException("Unknown type: %s" % publicKey.getType())

    @staticmethod
    def verifySignature(ecPublicSigningKey, message, signature):
        """
        :type ecPublicSigningKey: ECPublicKey
        :type message: bytearray
        :type signature: bytearray
        """

        if ecPublicSigningKey.getType() == Curve.DJB_TYPE:
            result = _curve.verifySignature(ecPublicSigningKey.getPublicKey(), message, signature)
            return result == 0
        else:
            raise InvalidKeyException("Unknown type: %s" % ecPublicSigningKey.getType())

    @staticmethod
    def calculateSignature(privateSigningKey, message):
        """
        :type privateSigningKey: ECPrivateKey
        :type  message: bytearray
        """
        if privateSigningKey.getType() == Curve.DJB_TYPE:
            rand = os.urandom(64)
            res = _curve.calculateSignature(rand, privateSigningKey.getPrivateKey(), message)
            return res
        else:
            raise InvalidKeyException("Unknown type: %s" % privateSigningKey.getType())


================================================
FILE: axolotl/ecc/djbec.py
================================================
# -*- coding: utf-8 -*-

import struct

from .ec import ECPublicKey, ECPrivateKey
from ..util.byteutil import ByteUtil


class DjbECPublicKey(ECPublicKey):

    def __init__(self, publicKey):
        self.publicKey = publicKey

    def serialize(self):
        from .curve import Curve

        combined = ByteUtil.combine([Curve.DJB_TYPE], self.publicKey)
        return bytes(combined)

    def getType(self):
        from .curve import Curve

        return Curve.DJB_TYPE

    def getPublicKey(self):
        return self.publicKey

    def __eq__(self, other):
        return self.publicKey == other.getPublicKey()

    def __lt__(self, other):
        myVal = struct.unpack(">8i", self.publicKey)
        otherVal = struct.unpack(">8i", other.getPublicKey())

        return myVal < otherVal

    def __cmp__(self, other):
        myVal = struct.unpack(">8i", self.publicKey)
        otherVal = struct.unpack(">8i", other.getPublicKey())

        if myVal < otherVal:
            return -1
        elif myVal == otherVal:
            return 0
        else:
            return 1


class DjbECPrivateKey(ECPrivateKey):
    def __init__(self, privateKey):
        self.privateKey = privateKey

    def getType(self):
        from .curve import Curve

        return Curve.DJB_TYPE

    def getPrivateKey(self):
        return self.privateKey

    def serialize(self):
        return self.privateKey

    def __eq__(self, other):
        return self.privateKey == other.getPrivateKey()


================================================
FILE: axolotl/ecc/ec.py
================================================
# -*- coding: utf-8 -*-

import abc


class ECPublicKey(object):
    __metaclass__ = abc.ABCMeta

    KEY_SIZE = 33

    @abc.abstractmethod
    def serialize(self):
        pass

    @abc.abstractmethod
    def getType(self):
        pass


class ECPrivateKey(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def serialize(self):
        pass

    @abc.abstractmethod
    def getType(self):
        pass


================================================
FILE: axolotl/ecc/eckeypair.py
================================================
# -*- coding: utf-8 -*-


class ECKeyPair():
    def __init__(self, publicKey, privateKey):
        """
        :type publicKey: ECPublicKey
        :type privateKey: ECPrivateKey
        """
        self.publicKey = publicKey
        self.privateKey = privateKey

    def getPrivateKey(self):
        return self.privateKey

    def getPublicKey(self):
        return self.publicKey


================================================
FILE: axolotl/groups/__init__.py
================================================
# -*- coding: utf-8 -*-


================================================
FILE: axolotl/groups/groupcipher.py
================================================
# -*- coding: utf-8 -*-

from ..invalidkeyidexception import InvalidKeyIdException
from ..invalidkeyexception import InvalidKeyException
from ..invalidmessageexception import InvalidMessageException
from ..duplicatemessagexception import DuplicateMessageException
from ..nosessionexception import NoSessionException
from ..protocol.senderkeymessage import SenderKeyMessage
from ..sessioncipher import AESCipher
from ..groups.state.senderkeystore import SenderKeyStore
class GroupCipher:
    def __init__(self, senderKeyStore, senderKeyName):
        """
        :type senderKeyStore: SenderKeyStore
        :type senderKeyName: SenderKeyName
        """
        self.senderKeyStore = senderKeyStore
        self.senderKeyName = senderKeyName

    def encrypt(self, paddedPlaintext):
        """
        :type paddedPlaintext: bytes
        """
        try:
            record = self.senderKeyStore.loadSenderKey(self.senderKeyName)
            senderKeyState = record.getSenderKeyState()
            senderKey = senderKeyState.getSenderChainKey().getSenderMessageKey()
            ciphertext = self.getCipherText(senderKey.getIv(), senderKey.getCipherKey(), paddedPlaintext)

            senderKeyMessage = SenderKeyMessage(senderKeyState.getKeyId(),
                                                senderKey.getIteration(),
                                                ciphertext,
                                                senderKeyState.getSigningKeyPrivate())

            senderKeyState.setSenderChainKey(senderKeyState.getSenderChainKey().getNext())
            self.senderKeyStore.storeSenderKey(self.senderKeyName, record)

            return senderKeyMessage.serialize()
        except InvalidKeyIdException as e:
            raise NoSessionException(e)

    def decrypt(self, senderKeyMessageBytes):
        """
        :type senderKeyMessageBytes: bytearray
        """
        try:
            record = self.senderKeyStore.loadSenderKey(self.senderKeyName)
            if record.isEmpty():
                raise NoSessionException("No sender key for: %s" % self.senderKeyName)
            senderKeyMessage = SenderKeyMessage(serialized = bytes(senderKeyMessageBytes))
            senderKeyState = record.getSenderKeyState(senderKeyMessage.getKeyId())

            senderKeyMessage.verifySignature(senderKeyState.getSigningKeyPublic())

            senderKey = self.getSenderKey(senderKeyState, senderKeyMessage.getIteration())

            plaintext = self.getPlainText(senderKey.getIv(), senderKey.getCipherKey(), senderKeyMessage.getCipherText())

            self.senderKeyStore.storeSenderKey(self.senderKeyName, record)

            return plaintext
        except (InvalidKeyException, InvalidKeyIdException) as e:
            raise InvalidMessageException(e)

    def getSenderKey(self, senderKeyState, iteration):
        senderChainKey = senderKeyState.getSenderChainKey()

        if senderChainKey.getIteration() > iteration:
            if senderKeyState.hasSenderMessageKey(iteration):
                return senderKeyState.removeSenderMessageKey(iteration)
            else:
                raise DuplicateMessageException("Received message with old counter: %s, %s" %
                                                (senderChainKey.getIteration(), iteration))

        if senderChainKey.getIteration() - iteration > 2000:
            raise InvalidMessageException("Over 2000 messages into the future!")

        while senderChainKey.getIteration() < iteration:
            senderKeyState.addSenderMessageKey(senderChainKey.getSenderMessageKey())
            senderChainKey = senderChainKey.getNext()

        senderKeyState.setSenderChainKey(senderChainKey.getNext())
        return senderChainKey.getSenderMessageKey()

    def getPlainText(self, iv, key, ciphertext):
        """
        :type iv: bytearray
        :type key: bytearray
        :type ciphertext: bytearray
        """
        try:
            cipher = AESCipher(key, iv)
            plaintext = cipher.decrypt(ciphertext)
            return plaintext
        except Exception as e:
            raise InvalidMessageException(e)

    def getCipherText(self, iv, key, plaintext):
        """
        :type iv: bytearray
        :type key: bytearray
        :type plaintext: bytearray
        """
        cipher = AESCipher(key, iv)
        return cipher.encrypt(plaintext)


================================================
FILE: axolotl/groups/groupsessionbuilder.py
================================================
# -*- coding: utf-8 -*-
from ..protocol.senderkeydistributionmessage import SenderKeyDistributionMessage
from ..invalidkeyidexception import InvalidKeyIdException
from ..invalidkeyexception import InvalidKeyException
from ..util.keyhelper import KeyHelper
class GroupSessionBuilder:
    def __init__(self, senderKeyStore):
        self.senderKeyStore = senderKeyStore

    def process(self, senderKeyName, senderKeyDistributionMessage):
        """
        :type senderKeyName: SenderKeyName
        :type senderKeyDistributionMessage: SenderKeyDistributionMessage
        """
        senderKeyRecord = self.senderKeyStore.loadSenderKey(senderKeyName)
        senderKeyRecord.addSenderKeyState(senderKeyDistributionMessage.getId(),
                                          senderKeyDistributionMessage.getIteration(),
                                          senderKeyDistributionMessage.getChainKey(),
                                          senderKeyDistributionMessage.getSignatureKey())
        self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord)


    def create(self, senderKeyName):
        """
        :type senderKeyName: SenderKeyName
        """
        try:
            senderKeyRecord = self.senderKeyStore.loadSenderKey(senderKeyName);

            if senderKeyRecord.isEmpty() :
                senderKeyRecord.setSenderKeyState(KeyHelper.generateSenderKeyId(),
                                                0,
                                                KeyHelper.generateSenderKey(),
                                                KeyHelper.generateSenderSigningKey());
                self.senderKeyStore.storeSenderKey(senderKeyName, senderKeyRecord);

            state = senderKeyRecord.getSenderKeyState();

            return SenderKeyDistributionMessage(state.getKeyId(),
                                                state.getSenderChainKey().getIteration(),
                                                state.getSenderChainKey().getSeed(),
                                                state.getSigningKeyPublic());
        except (InvalidKeyException, InvalidKeyIdException) as e:
            raise AssertionError(e)


================================================
FILE: axolotl/groups/ratchet/__init__.py
================================================
# -*- coding: utf-8 -*-


================================================
FILE: axolotl/groups/ratchet/senderchainkey.py
================================================
# -*- coding: utf-8 -*-

import hashlib
import hmac

from .sendermessagekey import SenderMessageKey


class SenderChainKey:
    MESSAGE_KEY_SEED = bytearray([0x01])
    CHAIN_KEY_SEED = bytearray([0x02])

    def __init__(self, iteration, chainKey):
        """
        :type iteration: int
        :type chainKey: bytearray
        """
        self.iteration = iteration
        self.chainKey = chainKey

    def getIteration(self):
        return self.iteration

    def getSenderMessageKey(self):
        return SenderMessageKey(self.iteration, self.getDerivative(self.__class__.MESSAGE_KEY_SEED, self.chainKey))

    def getNext(self):
        return SenderChainKey(self.iteration + 1, self.getDerivative(self.__class__.CHAIN_KEY_SEED, self.chainKey))

    def getSeed(self):
        return self.chainKey

    def getDerivative(self, seed, key):
        mac = hmac.new(bytes(key), bytes(seed), digestmod=hashlib.sha256)
        return mac.digest()


================================================
FILE: axolotl/groups/ratchet/sendermessagekey.py
================================================
# -*- coding: utf-8 -*-

from ...kdf.hkdfv3 import HKDFv3
from ...util.byteutil import ByteUtil


class SenderMessageKey:
    def __init__(self, iteration, seed):
        """
        :type iteration: int
        :type seed: bytearray
        """
        derivative = HKDFv3().deriveSecrets(seed, "WhisperGroup".encode(), 48)
        parts = ByteUtil.split(derivative, 16, 32)

        self.iteration = iteration
        self.seed = seed
        self.iv = parts[0]
        self.cipherKey = parts[1]

    def getIteration(self):
        return self.iteration

    def getIv(self):
        return self.iv

    def getCipherKey(self):
        return self.cipherKey

    def getSeed(self):
        return self.seed


================================================
FILE: axolotl/groups/senderkeyname.py
================================================
class SenderKeyName(object):
    def __init__(self, groupId, senderAxolotlAddress):
        self.groupId = groupId
        self.sender = senderAxolotlAddress

    def getGroupId(self):
        return self.groupId

    def getSender(self):
        return self.sender

    def serialize(self):
        return "%s::%s::%s" % (self.groupId, self.sender.getName(), self.sender.getDeviceId())

    def __eq__(self, other):
        if other is None: return False
        if other.__class__ != SenderKeyName: return False

        return self.groupId == other.getGroupId() and self.sender == other.getSender()

    def __hash__(self):
        return hash(self.groupId) ^ hash(self.sender)


================================================
FILE: axolotl/groups/state/__init__.py
================================================
# -*- coding: utf-8 -*-


================================================
FILE: axolotl/groups/state/senderkeyrecord.py
================================================
# -*- coding: utf-8 -*-

from ...state.storageprotos_pb2 import SenderKeyRecordStructure
from .senderkeystate import SenderKeyState
from ...invalidkeyidexception import InvalidKeyIdException


class SenderKeyRecord:
    def __init__(self, serialized=None):
        self.senderKeyStates = []

        if serialized:
            senderKeyRecordStructure = SenderKeyRecordStructure()
            senderKeyRecordStructure.ParseFromString(serialized)

            for structure in senderKeyRecordStructure.senderKeyStates:
                self.senderKeyStates.append(SenderKeyState(senderKeyStateStructure=structure))


    def isEmpty(self):
        return len(self.senderKeyStates) == 0

    def getSenderKeyState(self, keyId=None):
        if keyId is None:
            if len(self.senderKeyStates):
                return self.senderKeyStates[0]
            else:
                raise InvalidKeyIdException("No key state in record")
        else:
            for state in self.senderKeyStates:
                if state.getKeyId() == keyId:
                    return state
            raise InvalidKeyIdException("No keys for: %s" % keyId)

    def addSenderKeyState(self, id, iteration, chainKey, signatureKey):
        """
        :type id: int
        :type iteration: int
        :type chainKey: bytearray
        :type signatureKey: ECPublicKey
        """
        self.senderKeyStates.append(SenderKeyState(id, iteration, chainKey, signatureKey))

    def setSenderKeyState(self, id, iteration, chainKey, signatureKey):
        """
        :type id: int
        :type iteration: int
        :type chainKey: bytearray
        :type signatureKey: ECKeyPair
        """
        del self.senderKeyStates[:]
        self.senderKeyStates.append(SenderKeyState(id, iteration, chainKey, signatureKeyPair=signatureKey))

    def serialize(self):
        recordStructure = SenderKeyRecordStructure()

        for senderKeyState in self.senderKeyStates:
            recordStructure.senderKeyStates.extend([senderKeyState.getStructure()])

        return recordStructure.SerializeToString()

================================================
FILE: axolotl/groups/state/senderkeystate.py
================================================
# -*- coding: utf-8 -*-

from ...state import storageprotos_pb2 as storageprotos
from ..ratchet.senderchainkey import SenderChainKey
from ..ratchet.sendermessagekey import SenderMessageKey
from ...ecc.curve import Curve


class SenderKeyState:
    def __init__(self, id=None, iteration=None, chainKey=None,
                 signatureKeyPublic=None, signatureKeyPrivate=None,
                 signatureKeyPair=None, senderKeyStateStructure=None):
        """
        :type id: int
        :type iteration: int
        :type chainKey:  bytearray
        :type signatureKeyPublic:  ECPublicKey
        :type signatureKeyPrivate: ECPrivateKey
        :type signatureKeyPair: ECKeyPair
        :type senderKeyStateStructure: SenderKeyStateStructure
        """
        assert (bool(id) and bool(iteration) and bool(chainKey)) or \
               (bool(senderKeyStateStructure) ^ bool(signatureKeyPublic or signatureKeyPair)) or \
               (bool(signatureKeyPublic) ^ bool(signatureKeyPair)), "Missing required arguments"

        if senderKeyStateStructure:
            self.senderKeyStateStructure = senderKeyStateStructure
        else:
            if signatureKeyPair:
                signatureKeyPublic = signatureKeyPair.getPublicKey()
                signatureKeyPrivate = signatureKeyPair.getPrivateKey()

            self.senderKeyStateStructure = storageprotos.SenderKeyStateStructure()
            senderChainKeyStructure = self.senderKeyStateStructure.SenderChainKey()
            senderChainKeyStructure.iteration = iteration
            senderChainKeyStructure.seed = chainKey
            self.senderKeyStateStructure.senderChainKey.MergeFrom(senderChainKeyStructure)

            signingKeyStructure = self.senderKeyStateStructure.SenderSigningKey()
            signingKeyStructure.public = signatureKeyPublic.serialize()

            if signatureKeyPrivate:
                signingKeyStructure.private = signatureKeyPrivate.serialize()

            self.senderKeyStateStructure.senderKeyId = id
            self.senderChainKey = senderChainKeyStructure
            self.senderKeyStateStructure.senderSigningKey.CopyFrom(signingKeyStructure)

    def getKeyId(self):
        return self.senderKeyStateStructure.senderKeyId

    def getSenderChainKey(self):
        return SenderChainKey(self.senderKeyStateStructure.senderChainKey.iteration,
                              bytearray(self.senderKeyStateStructure.senderChainKey.seed))

    def setSenderChainKey(self, chainKey):
        self.senderKeyStateStructure.senderChainKey.iteration = chainKey.getIteration()
        self.senderKeyStateStructure.senderChainKey.seed = chainKey.getSeed()

    def getSigningKeyPublic(self):
        return Curve.decodePoint(bytearray(self.senderKeyStateStructure.senderSigningKey.public), 0)

    def getSigningKeyPrivate(self):
        return Curve.decodePrivatePoint(self.senderKeyStateStructure.senderSigningKey.private)

    def hasSenderMessageKey(self, iteration):
        for senderMessageKey in self.senderKeyStateStructure.senderMessageKeys:
            if senderMessageKey.iteration == iteration:
                return True

        return False

    def addSenderMessageKey(self, senderMessageKey):
        smk = self.senderKeyStateStructure.SenderMessageKey()
        smk.iteration = senderMessageKey.iteration
        smk.seed = senderMessageKey.seed
        self.senderKeyStateStructure.senderMessageKeys.extend([smk])

    def removeSenderMessageKey(self, iteration):
        keys = self.senderKeyStateStructure.senderMessageKeys
        result = None

        for i in range(0, len(keys)):
            senderMessageKey = keys[i]
            if senderMessageKey.iteration == iteration:
                result = senderMessageKey
                del keys[i]
                break

        if result is not None:
            return SenderMessageKey(result.iteration, bytearray(result.seed))

        return None

    def getStructure(self):
        return self.senderKeyStateStructure


================================================
FILE: axolotl/groups/state/senderkeystore.py
================================================
# -*- coding: utf-8 -*-

import abc


class SenderKeyStore(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def storeSenderKey(self, senderKeyId, senderKeyRecord):
        """
        :type senderKeyId: str
        :type senderKeyRecord: SenderKeyRecord
        """

    @abc.abstractmethod
    def loadSenderKey(self, senderKeyId):
        """
        :type senderKeyId: str
        """


================================================
FILE: axolotl/identitykey.py
================================================
# -*- coding: utf-8 -*-

from .ecc.curve import Curve


class IdentityKey:
    def __init__(self, ecPubKeyOrBytes, offset=None):
        if offset is None:
            self.publicKey = ecPubKeyOrBytes
        else:
            self.publicKey = Curve.decodePoint(bytearray(ecPubKeyOrBytes), offset)

    def getPublicKey(self):
        return self.publicKey

    def serialize(self):
        return self.publicKey.serialize()

    def get_fingerprint(self):
        raise Exception("IMPL ME")

    def __eq__(self, other):
        return self.publicKey == other.getPublicKey()

    def hashCode(self):
        raise Exception("IMPL ME")


================================================
FILE: axolotl/identitykeypair.py
================================================
# -*- coding: utf-8 -*-

from .state.storageprotos_pb2 import IdentityKeyPairStructure
from .identitykey import IdentityKey
from .ecc.curve import Curve


class IdentityKeyPair:
    def __init__(self, identityKeyPublicKey=None, ecPrivateKey=None, serialized=None):
        if serialized:
            structure = IdentityKeyPairStructure()
            structure.ParseFromString(serialized)
            self.publicKey = IdentityKey(bytearray(structure.publicKey), offset=0)
            self.privateKey = Curve.decodePrivatePoint(bytearray(structure.privateKey))
        else:
            self.publicKey = identityKeyPublicKey
            self.privateKey = ecPrivateKey

    def getPublicKey(self):
        return self.publicKey

    def getPrivateKey(self):
        return self.privateKey

    def serialize(self):
        structure = IdentityKeyPairStructure()
        structure.publicKey = self.publicKey.serialize()
        structure.privateKey = self.privateKey.serialize()
        return structure.SerializeToString()


================================================
FILE: axolotl/invalidkeyexception.py
================================================
# -*- coding: utf-8 -*-


class InvalidKeyException(Exception):
    pass


================================================
FILE: axolotl/invalidkeyidexception.py
================================================
# -*- coding: utf-8 -*-


class InvalidKeyIdException(Exception):
    pass


================================================
FILE: axolotl/invalidmessageexception.py
================================================
# -*- cofing: utf-8 -*-


class InvalidMessageException(Exception):
    def __init__(self, message, exceptions=None):
        if exceptions:
            message += str(exceptions[0])
        super(InvalidMessageException, self).__init__(message)


================================================
FILE: axolotl/invalidversionexception.py
================================================
# -*- coding: utf-8 -*-


class InvalidVersionException(Exception):
    pass


================================================
FILE: axolotl/kdf/__init__.py
================================================
# -*- coding: utf-8 -*-

__author__ = 'tarek'


================================================
FILE: axolotl/kdf/derivedmessagesecrets.py
================================================
# -*- coding: utf-8 -*-

from ..util.byteutil import ByteUtil


class DerivedMessageSecrets:
    SIZE = 80
    CIPHER_KEY_LENGTH = 32
    MAC_KEY_LENGTH = 32
    IV_LENGTH = 16

    def __init__(self, okm):
        keys = ByteUtil.split(okm,
                              self.__class__.CIPHER_KEY_LENGTH,
                              self.__class__.MAC_KEY_LENGTH,
                              self.__class__.IV_LENGTH)
        self.cipherKey = keys[0]  # AES
        self.macKey = keys[1]  # sha256
        self.iv = keys[2]

    def getCipherKey(self):
        return self.cipherKey

    def getMacKey(self):
        return self.macKey

    def getIv(self):
        return self.iv


================================================
FILE: axolotl/kdf/derivedrootsecrets.py
================================================
# -*- coding: utf-8 -*-

from ..util.byteutil import ByteUtil


class DerivedRootSecrets:
    SIZE = 64

    def __init__(self, okm):
        keys = ByteUtil.split(okm, 32, 32)
        self.rootKey = keys[0]
        self.chainKey = keys[1]

    def getRootKey(self):
        return self.rootKey

    def getChainKey(self):
        return self.chainKey


================================================
FILE: axolotl/kdf/hkdf.py
================================================
# -*- coding: utf-8 -*-

import abc
import hmac
import hashlib
import math


class HKDF(object):
    __metaclass__ = abc.ABCMeta
    HASH_OUTPUT_SIZE = 32

    @staticmethod
    def createFor(messageVersion):
        from .hkdfv2 import HKDFv2
        from .hkdfv3 import HKDFv3

        if messageVersion == 2:
            return HKDFv2()
        elif messageVersion == 3:
            return HKDFv3()
        else:
            raise AssertionError("Unknown version: %s " % messageVersion)

    def deriveSecrets(self, inputKeyMaterial, info, outputLength, salt=None):
        salt = salt or bytearray(self.__class__.HASH_OUTPUT_SIZE)
        prk = self.extract(salt, inputKeyMaterial)
        return self.expand(prk, info, outputLength)

    def extract(self, salt, inputKeyMaterial):
        mac = hmac.new(bytes(salt), digestmod=hashlib.sha256)
        mac.update(bytes(inputKeyMaterial))
        return mac.digest()

    def expand(self, prk, info, outputSize):
        iterations = int(math.ceil(float(outputSize) / float(self.__class__.HASH_OUTPUT_SIZE)))
        mixin = bytearray()
        results = bytearray()
        remainingBytes = outputSize

        for i in range(self.getIterationStartOffset(), iterations + self.getIterationStartOffset()):
            mac = hmac.new(prk, digestmod=hashlib.sha256)
            mac.update(bytes(mixin))
            if info is not None:
                mac.update(bytes(info))
            updateChr = chr(i % 256)
            mac.update(updateChr.encode())

            stepResult = mac.digest()
            stepSize = min(remainingBytes, len(stepResult))
            results.extend(stepResult[:stepSize])
            mixin = stepResult
            remainingBytes -= stepSize

        return bytes(results)

    @abc.abstractmethod
    def getIterationStartOffset(self):
        return 0


================================================
FILE: axolotl/kdf/hkdfv2.py
================================================
# -*- coding: utf-8 -*-

from .hkdf import HKDF


class HKDFv2(HKDF):
    def getIterationStartOffset(self):
        return 0


================================================
FILE: axolotl/kdf/hkdfv3.py
================================================
# -*- codsing: utf-8 -*-

from .hkdf import HKDF


class HKDFv3(HKDF):
    def getIterationStartOffset(self):
        return 1


================================================
FILE: axolotl/kdf/messagekeys.py
================================================
# -*- coding: utf-8 -*-


class MessageKeys:
    def __init__(self, cipherKey, macKey, iv, counter):
        self.cipherKey = cipherKey
        self.macKey = macKey
        self.iv = iv
        self.counter = counter

    def getCipherKey(self):
        return self.cipherKey

    def getMacKey(self):
        return self.macKey

    def getIv(self):
        return self.iv

    def getCounter(self):
        return self.counter


================================================
FILE: axolotl/legacymessageexception.py
================================================
# -*- coding: utf-8 -*-


class LegacyMessageException(Exception):
    pass


================================================
FILE: axolotl/nosessionexception.py
================================================
# -*- coding: utf-8 -*-


class NoSessionException(Exception):
    pass


================================================
FILE: axolotl/protobuf/LocalStorageProtocol.proto
================================================
package textsecure;

option java_package = "org.whispersystems.libaxolotl.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;
}

================================================
FILE: axolotl/protobuf/WhisperTextProtocol.proto
================================================
package textsecure;

option java_package = "org.whispersystems.libaxolotl.protocol";
option java_outer_classname = "WhisperProtos";

message WhisperMessage {
  optional bytes  ratchetKey      = 1;
  optional uint32 counter         = 2;
  optional uint32 previousCounter = 3;
  optional bytes  ciphertext      = 4;
}

message PreKeyWhisperMessage {
  optional uint32 registrationId = 5;
  optional uint32 preKeyId       = 1;
  optional uint32 signedPreKeyId = 6;
  optional bytes  baseKey        = 2;
  optional bytes  identityKey    = 3;
  optional bytes  message        = 4; // WhisperMessage
}

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;
}

================================================
FILE: axolotl/protocol/__init__.py
================================================
# -*- coding: utf-8 -*-

__author__ = 'tarek'


================================================
FILE: axolotl/protocol/ciphertextmessage.py
================================================
# -*- coding: utf-8 -*-

import abc


class CiphertextMessage(object):
    __metaclass__ = abc.ABCMeta

    UNSUPPORTED_VERSION = 1
    CURRENT_VERSION = 3

    WHISPER_TYPE = 2
    PREKEY_TYPE = 3
    SENDERKEY_TYPE = 4
    SENDERKEY_DISTRIBUTION_TYPE = 5

    # This should be the worst case (worse than V2). So not always accurate, but good enough for padding.
    ENCRYPTED_MESSAGE_OVERHEAD = 53

    @abc.abstractmethod
    def serialize(self):
        return

    @abc.abstractmethod
    def getType(self):
        return


================================================
FILE: axolotl/protocol/keyexchangemessage.py
================================================
# -*- coding: utf-8 -*-

from .ciphertextmessage import CiphertextMessage
from ..util.byteutil import ByteUtil
from . import whisperprotos_pb2 as whisperprotos
from ..legacymessageexception import LegacyMessageException
from ..invalidversionexception import InvalidVersionException
from ..invalidmessageexception import InvalidMessageException
from ..invalidkeyexception import InvalidKeyException
from ..ecc.curve import Curve
from ..identitykey import IdentityKey


class KeyExchangeMessage:
    INITIATE_FLAG = 0x01
    RESPONSE_FLAG = 0X02
    SIMULTAENOUS_INITIATE_FLAG = 0x04

    def __init__(self, messageVersion=None, sequence=None, flags=None, baseKey=None,
                 baseKeySignature=None, ratchetKey=None, identityKey=None, serialized=None):
        """
        :type messageVersion: int
        :type  sequence: int
        :type flags:int
        :type baseKey: ECPublicKey
        :type baseKeySignature: bytearray
        :type ratchetKey: ECPublicKey
        :type identityKey: IdentityKey
        :type serialized: bytearray
        """
        if serialized:
            try:
                parts = ByteUtil.split(serialized, 1, len(serialized) - 1)
                self.version = ByteUtil.highBitsToInt(parts[0][0])
                self.supportedVersion = ByteUtil.lowBitsToInt(parts[0][0])
                if self.version < CiphertextMessage.CURRENT_VERSION:
                    raise LegacyMessageException("Unsupportmessageed legacy version: %s" % self.version)
                if self.version > CiphertextMessage.CURRENT_VERSION:
                    raise InvalidVersionException("Unkown version: %s" % self.version)
                message = whisperprotos.KeyExchangeMessage()
                message.ParseFromString(bytes(parts[1]))

                if (not message.HasField("id") or not message.HasField("baseKey") or
                        not message.HasField("ratchetKey") or not message.HasField("identityKey") or
                        not message.HasField("baseKeySignature")):
                    raise InvalidMessageException("Some required fields are missing!")

                self.sequence = message.id >> 5
                self.flags = message.id & 0x1f
                self.serialized = serialized
                self.baseKey = Curve.decodePoint(bytearray(message.baseKey), 0)
                self.baseKeySignature = message.baseKeySignature
                self.ratchetKey = Curve.decodePoint(bytearray(message.ratchetKey), 0)
                self.identityKey = IdentityKey(message.identityKey, 0)

            except InvalidKeyException as e:
                raise InvalidMessageException(e)
        else:
            self.supportedVersion = CiphertextMessage.CURRENT_VERSION
            self.version = messageVersion
            self.sequence = sequence
            self.flags = flags
            self.baseKey = baseKey
            self.baseKeySignature = baseKeySignature
            self.ratchetKey = ratchetKey
            self.identityKey = identityKey

            version = [ByteUtil.intsToByteHighAndLow(self.version, self.supportedVersion)]
            keyExchangeMessage = whisperprotos.KeyExchangeMessage()
            keyExchangeMessage.id = (self.sequence << 5) | self.flags
            keyExchangeMessage.baseKey = baseKey.serialize()
            keyExchangeMessage.ratchetKey = ratchetKey.serialize()
            keyExchangeMessage.identityKey = identityKey.serialize()

            if messageVersion >= 3:
                keyExchangeMessage.baseKeySignature = baseKeySignature

            self.serialized = ByteUtil.combine(version, keyExchangeMessage.SerializeToString())

    def getVersion(self):
        return self.version

    def getBaseKey(self):
        return self.baseKey

    def getBaseKeySignature(self):
        return self.baseKeySignature

    def getRatchetKey(self):
        return self.ratchetKey

    def getIdentityKey(self):
        return self.identityKey

    def hasIdentityKey(self):
        return True

    def getMaxVersion(self):
        return self.supportedVersion

    def isResponse(self):
        return ((self.flags & self.__class__.RESPONSE_FLAG) != 0)

    def isInitiate(self):
        return (self.flags & self.__class__.INITIATE_FLAG) != 0

    def isResponseForSimultaneousInitiate(self):
        return (self.flags & self.__class__.SIMULTAENOUS_INITIATE_FLAG) != 0

    def getFlags(self):
        return self.flags

    def getSequence(self):
        return self.sequence

    def serialize(self):
        return self.serialized


================================================
FILE: axolotl/protocol/prekeywhispermessage.py
================================================
# -*- coding: utf-8 -*-

from google.protobuf.message import DecodeError

from .ciphertextmessage import CiphertextMessage
from ..util.byteutil import ByteUtil
from ..ecc.curve import Curve
from ..identitykey import IdentityKey
from .whispermessage import WhisperMessage
from ..invalidversionexception import InvalidVersionException
from ..invalidmessageexception import InvalidMessageException
from ..legacymessageexception import LegacyMessageException
from ..invalidkeyexception import InvalidKeyException
from . import whisperprotos_pb2 as whisperprotos


class PreKeyWhisperMessage(CiphertextMessage):
    def __init__(self, messageVersion=None, registrationId=None, preKeyId=None,
                 signedPreKeyId=None, ecPublicBaseKey=None, identityKey=None,
                 whisperMessage=None, serialized=None):
        if serialized:
            try:
                self.version = ByteUtil.highBitsToInt(serialized[0])
                if self.version > CiphertextMessage.CURRENT_VERSION:
                    raise InvalidVersionException("Unknown version %s" % self.version)

                if self.version < CiphertextMessage.CURRENT_VERSION:
                    raise LegacyMessageException("Legacy version: %s" % self.version)

                preKeyWhisperMessage = whisperprotos.PreKeyWhisperMessage()
                preKeyWhisperMessage.ParseFromString(serialized[1:])

                if preKeyWhisperMessage.signedPreKeyId is None or \
                        not preKeyWhisperMessage.baseKey or \
                        not preKeyWhisperMessage.identityKey or \
                        not preKeyWhisperMessage.message:
                    raise InvalidMessageException("Incomplete message")

                self.serialized = serialized
                self.registrationId = preKeyWhisperMessage.registrationId
                self.preKeyId = preKeyWhisperMessage.preKeyId
                if preKeyWhisperMessage.signedPreKeyId is not None:
                    self.signedPreKeyId = preKeyWhisperMessage.signedPreKeyId
                else:
                    self.signedPreKeyId = -1

                self.baseKey = Curve.decodePoint(bytearray(preKeyWhisperMessage.baseKey), 0)

                self.identityKey = IdentityKey(Curve.decodePoint(bytearray(preKeyWhisperMessage.identityKey), 0))
                self.message = WhisperMessage(serialized=preKeyWhisperMessage.message)
            except (InvalidKeyException, LegacyMessageException, DecodeError) as e:
                raise InvalidMessageException(e)

        else:
            self.version = messageVersion
            self.registrationId = registrationId
            self.preKeyId = preKeyId
            self.signedPreKeyId = signedPreKeyId
            self.baseKey = ecPublicBaseKey
            self.identityKey = identityKey
            self.message = whisperMessage

            builder = whisperprotos.PreKeyWhisperMessage()
            builder.signedPreKeyId = signedPreKeyId
            builder.baseKey = ecPublicBaseKey.serialize()
            builder.identityKey = identityKey.serialize()
            builder.message = whisperMessage.serialize()
            builder.registrationId = registrationId

            if preKeyId is not None:
                builder.preKeyId = preKeyId

            versionBytes = ByteUtil.intsToByteHighAndLow(self.version, self.__class__.CURRENT_VERSION)
            messageBytes = builder.SerializeToString()
            self.serialized = bytes(ByteUtil.combine(versionBytes, messageBytes))

    def getMessageVersion(self):
        return self.version

    def getIdentityKey(self):
        return self.identityKey

    def getRegistrationId(self):
        return self.registrationId

    def getPreKeyId(self):
        return self.preKeyId

    def getSignedPreKeyId(self):
        return self.signedPreKeyId

    def getBaseKey(self):
        return self.baseKey

    def getWhisperMessage(self):
        return self.message

    def serialize(self):
        return self.serialized

    def getType(self):
        return CiphertextMessage.PREKEY_TYPE


================================================
FILE: axolotl/protocol/senderkeydistributionmessage.py
================================================
# -*- coding: utf-8 -*-

from .ciphertextmessage import CiphertextMessage
from . import whisperprotos_pb2 as whisperprotos
from ..util.byteutil import ByteUtil
from ..legacymessageexception import LegacyMessageException
from ..invalidmessageexception import InvalidMessageException
from ..invalidkeyexception import InvalidKeyException
from ..ecc.curve import Curve
class SenderKeyDistributionMessage(CiphertextMessage):
    def __init__(self, id=None, iteration=None, chainKey=None, signatureKey=None, serialized=None):
        """
        :type id: int
        :type iteration: int
        :type chainKey: bytearray
        :type signatureKey: ECPublicKey
        """


        assert bool(id is not None and iteration is not None and chainKey is not None and signatureKey is not None)\
               ^ bool(serialized),\
            "Either pass arguments or serialized data"

        if serialized:
            try:
                messageParts = ByteUtil.split(serialized, 1, len(serialized)- 1)
                version = messageParts[0][0]
                message = messageParts[1]


                if ByteUtil.highBitsToInt(version) < 3:
                    raise LegacyMessageException("Legacy message: %s" % ByteUtil.highBitsToInt(version))

                if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION:
                    raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version))


                distributionMessage = whisperprotos.SenderKeyDistributionMessage()
                distributionMessage.ParseFromString(message)

                if distributionMessage.id is None or distributionMessage.iteration is None\
                    or distributionMessage.chainKey is None or distributionMessage.signingKey is None:
                    raise InvalidMessageException("Incomplete message")

                self.serialized = serialized

                self.id           = distributionMessage.id
                self.iteration    = distributionMessage.iteration
                self.chainKey     = distributionMessage.chainKey
                self.signatureKey = Curve.decodePoint(bytearray(distributionMessage.signingKey), 0)

            except Exception as e:
                raise InvalidMessageException(e)
        else:
            version = [ByteUtil.intsToByteHighAndLow(self.__class__.CURRENT_VERSION, self.__class__.CURRENT_VERSION)]
            self.id = id
            self.iteration = iteration
            self.chainKey = chainKey
            self.signatureKey = signatureKey
            message = whisperprotos.SenderKeyDistributionMessage()
            message.id = id
            message.iteration = iteration
            message.chainKey= bytes(chainKey)
            message.signingKey = signatureKey.serialize()
            message = message.SerializeToString()
            self.serialized = bytes(ByteUtil.combine(version, message))

    def serialize(self):
        return self.serialized

    def getType(self):
        return self.__class__.SENDERKEY_DISTRIBUTION_TYPE

    def getIteration(self):
        return self.iteration

    def getChainKey(self):
        return self.chainKey

    def getSignatureKey(self):
        return self.signatureKey

    def getId(self):
        return self.id

================================================
FILE: axolotl/protocol/senderkeymessage.py
================================================
# -*- coding: utf-8 -*-

from .ciphertextmessage import CiphertextMessage
from ..util.byteutil import ByteUtil
from ..legacymessageexception import LegacyMessageException
from ..invalidmessageexception import InvalidMessageException
from ..invalidkeyexception import InvalidKeyException
from ..ecc.curve import Curve
from . import whisperprotos_pb2 as whisperprotos


class SenderKeyMessage(CiphertextMessage):
    SIGNATURE_LENGTH = 64

    def __init__(self, keyId=None, iteration=None, ciphertext=None, signatureKey=None, serialized=None):
        assert bool(keyId is not None and iteration is not None and ciphertext is not None and
                    signatureKey is not None) ^ bool(serialized), "Either pass arguments or serialized data"

        if serialized:
            try:
                messageParts = ByteUtil.split(serialized, 1, len(serialized) - 1 - self.__class__.SIGNATURE_LENGTH,
                                              self.__class__.SIGNATURE_LENGTH)

                version = messageParts[0][0]
                message = messageParts[1]
                signature = messageParts[2]

                if ByteUtil.highBitsToInt(version) < 3:
                    raise LegacyMessageException("Legacy message: %s" % ByteUtil.highBitsToInt(version))

                if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION:
                    raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version))

                senderKeyMessage = whisperprotos.SenderKeyMessage()
                senderKeyMessage.ParseFromString(message)

                if senderKeyMessage.id is None or senderKeyMessage.iteration is None or \
                        senderKeyMessage.ciphertext is None:
                    raise InvalidMessageException("Incomplete message")

                self.serialized = serialized
                self.messageVersion = ByteUtil.highBitsToInt(version)

                self.keyId = senderKeyMessage.id
                self.iteration = senderKeyMessage.iteration
                self.ciphertext = senderKeyMessage.ciphertext
            except Exception as e:
                raise InvalidMessageException(e)
        else:
            version = [ByteUtil.intsToByteHighAndLow(self.__class__.CURRENT_VERSION, self.__class__.CURRENT_VERSION)]

            message = whisperprotos.SenderKeyMessage()
            message.id = keyId
            message.iteration = iteration
            message.ciphertext = ciphertext
            message = message.SerializeToString()

            signature = self.getSignature(signatureKey, bytes(ByteUtil.combine(version, message)))

            self.serialized = bytes(ByteUtil.combine(version, message, signature))
            self.messageVersion = self.__class__.CURRENT_VERSION
            self.keyId = keyId
            self.iteration = iteration
            self.ciphertext = ciphertext


    def getKeyId(self):
        return self.keyId

    def getIteration(self):
        return self.iteration

    def getCipherText(self):
        return self.ciphertext

    def verifySignature(self, signatureKey):
        """
        :type signatureKey: ECPublicKey
        """
        try:
            parts = ByteUtil.split(self.serialized,
                                   len(self.serialized) - self.__class__.SIGNATURE_LENGTH,
                                   self.__class__.SIGNATURE_LENGTH)

            if not Curve.verifySignature(signatureKey, parts[0], parts[1]):
                raise InvalidMessageException("Invalid signature!")
        except InvalidKeyException as e:
            raise InvalidMessageException(e)

    def getSignature(self, signatureKey, serialized):
        """
        :type signatureKey: ECPrivateKey
        :type serialized: bytearray
        """
        try:
            return Curve.calculateSignature(signatureKey, serialized)
        except InvalidKeyException as e:
            raise AssertionError(e)

    def serialize(self):
        return self.serialized

    def getType(self):
        return CiphertextMessage.SENDERKEY_TYPE

================================================
FILE: axolotl/protocol/whispermessage.py
================================================
# -*- cosing: utf-8 -*-

import hmac
import hashlib

from .ciphertextmessage import CiphertextMessage
from ..util.byteutil import ByteUtil
from ..ecc.curve import Curve
from . import whisperprotos_pb2 as whisperprotos
from ..legacymessageexception import LegacyMessageException
from ..invalidmessageexception import InvalidMessageException
from ..invalidkeyexception import InvalidKeyException


class WhisperMessage(CiphertextMessage):
    MAC_LENGTH = 8

    def __init__(self, messageVersion=None, macKey=None, ECPublicKey_senderRatchetKey=None,
                 counter=None, previousCounter=None, ciphertext=None, senderIdentityKey=None,
                 receiverIdentityKey=None, serialized=None):
        self.serialized = ""
        if serialized:
            try:
                assert type(serialized) in (str, bytes), "Expected serialized %s, got %s" % (str, type(serialized))
                messageParts = ByteUtil.split(serialized, 1, len(serialized) - 1 - WhisperMessage.MAC_LENGTH,
                                              WhisperMessage.MAC_LENGTH)
                version = messageParts[0][0]
                message = messageParts[1]
                mac = messageParts[2]

                if ByteUtil.highBitsToInt(version) <= self.__class__.UNSUPPORTED_VERSION:
                    raise LegacyMessageException("Legacy message %s" % ByteUtil.highBitsToInt(version))

                if ByteUtil.highBitsToInt(version) > self.__class__.CURRENT_VERSION:
                    raise InvalidMessageException("Unknown version: %s" % ByteUtil.highBitsToInt(version))

                whisperMessage = whisperprotos.WhisperMessage()
                whisperMessage.ParseFromString(message)

                if not whisperMessage.ciphertext or whisperMessage.counter is None or not whisperMessage.ratchetKey:
                    raise InvalidMessageException("Incomplete message")

                self.serialized = serialized
                self.senderRatchetKey = Curve.decodePoint(bytearray(whisperMessage.ratchetKey), 0)
                self.messageVersion = ByteUtil.highBitsToInt(version)
                self.counter = whisperMessage.counter
                self.previousCounter = whisperMessage.previousCounter
                self.ciphertext = whisperMessage.ciphertext
            except InvalidKeyException as e:
                raise InvalidMessageException(e)
        else:
            version = ByteUtil.intsToByteHighAndLow(messageVersion, self.__class__.CURRENT_VERSION)
            message = whisperprotos.WhisperMessage()
            message.ratchetKey = ECPublicKey_senderRatchetKey.serialize()
            message.counter = counter
            message.previousCounter = previousCounter
            message.ciphertext = ciphertext
            message = message.SerializeToString()
            mac = self.getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey,
                              ByteUtil.combine(version, message))
            self.serialized = bytes(ByteUtil.combine(version, message, mac))
            self.senderRatchetKey = ECPublicKey_senderRatchetKey
            self.counter = counter
            self.previousCounter = previousCounter
            self.ciphertext = ciphertext
            self.messageVersion = messageVersion

    def getSenderRatchetKey(self):
        return self.senderRatchetKey

    def getMessageVersion(self):
        return self.messageVersion

    def getCounter(self):
        return self.counter

    def getBody(self):
        return self.ciphertext

    def verifyMac(self, messageVersion, senderIdentityKey, receiverIdentityKey, macKey):
        parts = ByteUtil.split(self.serialized,
                               len(self.serialized) - self.__class__.MAC_LENGTH,
                               self.__class__.MAC_LENGTH)
        ourMac = self.getMac(messageVersion, senderIdentityKey, receiverIdentityKey, macKey, parts[0])
        theirMac = parts[1]

        if ourMac != theirMac:
            raise InvalidMessageException("Bad Mac!")

    def getMac(self, messageVersion, senderIdentityKey, receiverIdentityKey, macKey, serialized):
        mac = hmac.new(macKey, digestmod=hashlib.sha256)
        if messageVersion >= 3:
            mac.update(senderIdentityKey.getPublicKey().serialize())
            mac.update(receiverIdentityKey.getPublicKey().serialize())

        mac.update(bytes(serialized))
        fullMac = mac.digest()
        return ByteUtil.trim(fullMac, self.__class__.MAC_LENGTH)

    def serialize(self):
        return self.serialized

    def getType(self):
        return CiphertextMessage.WHISPER_TYPE

    def isLegacy(self, message):
        return message is not None and \
                len(message) >= 1 and \
                ByteUtil.highBitsToInt(message[0]) <= CiphertextMessage.UNSUPPORTED_VERSION


================================================
FILE: axolotl/protocol/whisperprotos_pb2.py
================================================
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: WhisperTextProtocol.proto

import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()




DESCRIPTOR = _descriptor.FileDescriptor(
  name='WhisperTextProtocol.proto',
  package='textsecure',
  serialized_pb=_b('\n\x19WhisperTextProtocol.proto\x12\ntextsecure\"b\n\x0eWhisperMessage\x12\x12\n\nratchetKey\x18\x01 \x01(\x0c\x12\x0f\n\x07\x63ounter\x18\x02 \x01(\r\x12\x17\n\x0fpreviousCounter\x18\x03 \x01(\r\x12\x12\n\nciphertext\x18\x04 \x01(\x0c\"\x8f\x01\n\x14PreKeyWhisperMessage\x12\x16\n\x0eregistrationId\x18\x05 \x01(\r\x12\x10\n\x08preKeyId\x18\x01 \x01(\r\x12\x16\n\x0esignedPreKeyId\x18\x06 \x01(\r\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\x12\x13\n\x0bidentityKey\x18\x03 \x01(\x0c\x12\x0f\n\x07message\x18\x04 \x01(\x0c\"t\n\x12KeyExchangeMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\x12\x12\n\nratchetKey\x18\x03 \x01(\x0c\x12\x13\n\x0bidentityKey\x18\x04 \x01(\x0c\x12\x18\n\x10\x62\x61seKeySignature\x18\x05 \x01(\x0c\"E\n\x10SenderKeyMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\titeration\x18\x02 \x01(\r\x12\x12\n\nciphertext\x18\x03 \x01(\x0c\"c\n\x1cSenderKeyDistributionMessage\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\titeration\x18\x02 \x01(\r\x12\x10\n\x08\x63hainKey\x18\x03 \x01(\x0c\x12\x12\n\nsigningKey\x18\x04 \x01(\x0c\x42\x37\n&org.whispersystems.libaxolotl.protocolB\rWhisperProtos')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)




_WHISPERMESSAGE = _descriptor.Descriptor(
  name='WhisperMessage',
  full_name='textsecure.WhisperMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='ratchetKey', full_name='textsecure.WhisperMessage.ratchetKey', index=0,
      number=1, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='counter', full_name='textsecure.WhisperMessage.counter', index=1,
      number=2, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='previousCounter', full_name='textsecure.WhisperMessage.previousCounter', index=2,
      number=3, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='ciphertext', full_name='textsecure.WhisperMessage.ciphertext', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=41,
  serialized_end=139,
)


_PREKEYWHISPERMESSAGE = _descriptor.Descriptor(
  name='PreKeyWhisperMessage',
  full_name='textsecure.PreKeyWhisperMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='registrationId', full_name='textsecure.PreKeyWhisperMessage.registrationId', index=0,
      number=5, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='preKeyId', full_name='textsecure.PreKeyWhisperMessage.preKeyId', index=1,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='signedPreKeyId', full_name='textsecure.PreKeyWhisperMessage.signedPreKeyId', index=2,
      number=6, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='baseKey', full_name='textsecure.PreKeyWhisperMessage.baseKey', index=3,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='identityKey', full_name='textsecure.PreKeyWhisperMessage.identityKey', index=4,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='message', full_name='textsecure.PreKeyWhisperMessage.message', index=5,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=142,
  serialized_end=285,
)


_KEYEXCHANGEMESSAGE = _descriptor.Descriptor(
  name='KeyExchangeMessage',
  full_name='textsecure.KeyExchangeMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='id', full_name='textsecure.KeyExchangeMessage.id', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='baseKey', full_name='textsecure.KeyExchangeMessage.baseKey', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='ratchetKey', full_name='textsecure.KeyExchangeMessage.ratchetKey', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='identityKey', full_name='textsecure.KeyExchangeMessage.identityKey', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='baseKeySignature', full_name='textsecure.KeyExchangeMessage.baseKeySignature', index=4,
      number=5, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=287,
  serialized_end=403,
)


_SENDERKEYMESSAGE = _descriptor.Descriptor(
  name='SenderKeyMessage',
  full_name='textsecure.SenderKeyMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='id', full_name='textsecure.SenderKeyMessage.id', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='iteration', full_name='textsecure.SenderKeyMessage.iteration', index=1,
      number=2, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='ciphertext', full_name='textsecure.SenderKeyMessage.ciphertext', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=405,
  serialized_end=474,
)


_SENDERKEYDISTRIBUTIONMESSAGE = _descriptor.Descriptor(
  name='SenderKeyDistributionMessage',
  full_name='textsecure.SenderKeyDistributionMessage',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='id', full_name='textsecure.SenderKeyDistributionMessage.id', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='iteration', full_name='textsecure.SenderKeyDistributionMessage.iteration', index=1,
      number=2, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='chainKey', full_name='textsecure.SenderKeyDistributionMessage.chainKey', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='signingKey', full_name='textsecure.SenderKeyDistributionMessage.signingKey', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=476,
  serialized_end=575,
)

DESCRIPTOR.message_types_by_name['WhisperMessage'] = _WHISPERMESSAGE
DESCRIPTOR.message_types_by_name['PreKeyWhisperMessage'] = _PREKEYWHISPERMESSAGE
DESCRIPTOR.message_types_by_name['KeyExchangeMessage'] = _KEYEXCHANGEMESSAGE
DESCRIPTOR.message_types_by_name['SenderKeyMessage'] = _SENDERKEYMESSAGE
DESCRIPTOR.message_types_by_name['SenderKeyDistributionMessage'] = _SENDERKEYDISTRIBUTIONMESSAGE

WhisperMessage = _reflection.GeneratedProtocolMessageType('WhisperMessage', (_message.Message,), dict(
  DESCRIPTOR = _WHISPERMESSAGE,
  __module__ = 'WhisperTextProtocol_pb2'
  # @@protoc_insertion_point(class_scope:textsecure.WhisperMessage)
  ))
_sym_db.RegisterMessage(WhisperMessage)

PreKeyWhisperMessage = _reflection.GeneratedProtocolMessageType('PreKeyWhisperMessage', (_message.Message,), dict(
  DESCRIPTOR = _PREKEYWHISPERMESSAGE,
  __module__ = 'WhisperTextProtocol_pb2'
  # @@protoc_insertion_point(class_scope:textsecure.PreKeyWhisperMessage)
  ))
_sym_db.RegisterMessage(PreKeyWhisperMessage)

KeyExchangeMessage = _reflection.GeneratedProtocolMessageType('KeyExchangeMessage', (_message.Message,), dict(
  DESCRIPTOR = _KEYEXCHANGEMESSAGE,
  __module__ = 'WhisperTextProtocol_pb2'
  # @@protoc_insertion_point(class_scope:textsecure.KeyExchangeMessage)
  ))
_sym_db.RegisterMessage(KeyExchangeMessage)

SenderKeyMessage = _reflection.GeneratedProtocolMessageType('SenderKeyMessage', (_message.Message,), dict(
  DESCRIPTOR = _SENDERKEYMESSAGE,
  __module__ = 'WhisperTextProtocol_pb2'
  # @@protoc_insertion_point(class_scope:textsecure.SenderKeyMessage)
  ))
_sym_db.RegisterMessage(SenderKeyMessage)

SenderKeyDistributionMessage = _reflection.GeneratedProtocolMessageType('SenderKeyDistributionMessage', (_message.Message,), dict(
  DESCRIPTOR = _SENDERKEYDISTRIBUTIONMESSAGE,
  __module__ = 'WhisperTextProtocol_pb2'
  # @@protoc_insertion_point(class_scope:textsecure.SenderKeyDistributionMessage)
  ))
_sym_db.RegisterMessage(SenderKeyDistributionMessage)


DESCRIPTOR.has_options = True
DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n&org.whispersystems.libaxolotl.protocolB\rWhisperProtos'))
# @@protoc_insertion_point(module_scope)


================================================
FILE: axolotl/ratchet/__init__.py
================================================
# -*- coding: utf-8 -*-


================================================
FILE: axolotl/ratchet/aliceaxolotlparameters.py
================================================
# -*- coding: utf-8 -*-


class AliceAxolotlParameters:
    def __init__(self, ourIdentityKey, ourBaseKey, theirIdentityKey, theirSignedPreKey,
                 theirRatchetKey, theirOneTimePreKey):
        """
        :type ourBaseKey: ECKeyPair
        :type theirSignedPreKey: ECKeyPair
        :type ourIdentityKey: IdentityKeyPair
        :type theirOneTimePreKey: ECPublicKey
        :type theirRatchetKey: ECKeyPair
        :type theirIdentityKey: IdentityKey
        """
        self.ourBaseKey = ourBaseKey
        self.ourIdentityKey = ourIdentityKey
        self.theirSignedPreKey = theirSignedPreKey
        self.theirRatchetKey = theirRatchetKey
        self.theirIdentityKey = theirIdentityKey
        self.theirOneTimePreKey = theirOneTimePreKey

        if ourBaseKey is None or ourIdentityKey is None or theirSignedPreKey is None \
                or theirRatchetKey is None or theirIdentityKey is None or theirSignedPreKey is None:
            raise ValueError("Null value!")

    def getOurIdentityKey(self):
        return self.ourIdentityKey

    def getOurBaseKey(self):
        return self.ourBaseKey

    def getTheirIdentityKey(self):
        return self.theirIdentityKey

    def getTheirSignedPreKey(self):
        return self.theirSignedPreKey

    def getTheirOneTimePreKey(self):
        return self.theirOneTimePreKey

    def getTheirRatchetKey(self):
        return self.theirRatchetKey

    @staticmethod
    def newBuilder():
        return AliceAxolotlParameters.Builder()

    class Builder:
        def __init__(self):
            self.ourIdentityKey = None
            self.ourBaseKey = None
            self.theirIdentityKey = None
            self.theirSignedPreKey = None
            self.theirRatchetKey = None
            self.theirOneTimePreKey = None

        def setOurIdentityKey(self, ourIdentityKey):
            self.ourIdentityKey = ourIdentityKey
            return self

        def setOurBaseKey(self, ourBaseKey):
            self.ourBaseKey = ourBaseKey
            return self

        def setTheirRatchetKey(self, theirRatchetKey):
            self.theirRatchetKey = theirRatchetKey
            return self

        def setTheirIdentityKey(self, theirIdentityKey):
            self.theirIdentityKey = theirIdentityKey
            return self

        def setTheirSignedPreKey(self, theirSignedPreKey):
            self.theirSignedPreKey = theirSignedPreKey
            return self

        def setTheirOneTimePreKey(self, theirOneTimePreKey):
            self.theirOneTimePreKey = theirOneTimePreKey
            return self

        def create(self):
            return AliceAxolotlParameters(self.ourIdentityKey, self.ourBaseKey, self.theirIdentityKey,
                                          self.theirSignedPreKey, self.theirRatchetKey, self.theirOneTimePreKey)


================================================
FILE: axolotl/ratchet/bobaxolotlparamaters.py
================================================
# -*- coding: utf-8 -*-


class BobAxolotlParameters:
    def __init__(self, ourIdentityKey, ourSignedPreKey, ourRatchetKey, ourOneTimePreKey,
                 theirIdentityKey, theirBaseKey):
        """
        :type ourIdentityKey: IdentityKeyPair
        :type ourSignedPreKey: ECKeyPair
        :type ourRatchetKey: ECKeyPair
        :type ourOneTimePreKey: ECKeyPair
        :type theirIdentityKey: IdentityKey
        :type theirBaseKey: ECPublicKey
        """
        self.ourIdentityKey = ourIdentityKey
        self.ourSignedPreKey = ourSignedPreKey
        self.ourRatchetKey = ourRatchetKey
        self.ourOneTimePreKey = ourOneTimePreKey
        self.theirIdentityKey = theirIdentityKey
        self.theirBaseKey = theirBaseKey

        if ourIdentityKey is None or ourSignedPreKey is None or ourRatchetKey is None \
                or theirIdentityKey is None or theirBaseKey is None:
            raise ValueError("Null value!")

    def getOurIdentityKey(self):
        return self.ourIdentityKey

    def getOurSignedPreKey(self):
        return self.ourSignedPreKey

    def getOurOneTimePreKey(self):
        return self.ourOneTimePreKey

    def getTheirIdentityKey(self):
        return self.theirIdentityKey

    def getTheirBaseKey(self):
        return self.theirBaseKey

    def getOurRatchetKey(self):
        return self.ourRatchetKey

    @staticmethod
    def newBuilder():
        return BobAxolotlParameters.Builder()

    class Builder:
        def __init__(self):
            self.ourIdentityKey = None
            self.ourSignedPreKey = None
            self.ourOneTimePreKey = None
            self.ourRatchetKey = None
            self.theirIdentityKey = None
            self.theirBaseKey = None

        def setOurIdentityKey(self, ourIdentityKey):
            self.ourIdentityKey = ourIdentityKey
            return self

        def setOurSignedPreKey(self, ourSignedPreKey):
            self.ourSignedPreKey = ourSignedPreKey
            return self

        def setOurOneTimePreKey(self, ourOneTimePreKey):
            self.ourOneTimePreKey = ourOneTimePreKey
            return self

        def setOurRatchetKey(self, ourRatchetKey):
            self.ourRatchetKey = ourRatchetKey
            return self

        def setTheirIdentityKey(self, theirIdentityKey):
            self.theirIdentityKey = theirIdentityKey
            return self

        def setTheirBaseKey(self, theirBaseKey):
            self.theirBaseKey = theirBaseKey
            return self

        def create(self):
            return BobAxolotlParameters(self.ourIdentityKey, self.ourSignedPreKey, self.ourRatchetKey,
                                        self.ourOneTimePreKey, self.theirIdentityKey, self.theirBaseKey)


================================================
FILE: axolotl/ratchet/chainkey.py
================================================
# -*- coding: utf-8 -*-

import hmac
import hashlib

from ..kdf.derivedmessagesecrets import DerivedMessageSecrets
from ..kdf.messagekeys import MessageKeys


class ChainKey:
    MESSAGE_KEY_SEED = bytearray([0x01])
    CHAIN_KEY_SEED = bytearray([0x02])

    def __init__(self, kdf, key, index):
        self.kdf = kdf
        self.key = key
        self.index = index

    def getKey(self):
        return self.key

    def getIndex(self):
        return self.index

    def getNextChainKey(self):
        nextKey = self.getBaseMaterial(self.__class__.CHAIN_KEY_SEED)
        return ChainKey(self.kdf, nextKey, self.index + 1)

    def getMessageKeys(self):
        inputKeyMaterial = self.getBaseMaterial(self.__class__.MESSAGE_KEY_SEED)
        keyMaterialBytes = self.kdf.deriveSecrets(inputKeyMaterial,
                                                  bytearray("WhisperMessageKeys".encode()),
                                                  DerivedMessageSecrets.SIZE)
        keyMaterial = DerivedMessageSecrets(keyMaterialBytes)
        return MessageKeys(keyMaterial.getCipherKey(), keyMaterial.getMacKey(), keyMaterial.getIv(), self.index)

    def getBaseMaterial(self, seedBytes):
        mac = hmac.new(bytes(self.key), digestmod=hashlib.sha256)
        mac.update(bytes(seedBytes))
        return mac.digest()


================================================
FILE: axolotl/ratchet/ratchetingsession.py
================================================
# -*- coding: utf-8 -*-

from ..ecc.curve import Curve
from .bobaxolotlparamaters import BobAxolotlParameters
from .aliceaxolotlparameters import AliceAxolotlParameters
from ..kdf.hkdfv3 import HKDFv3
from ..util.byteutil import ByteUtil
from .rootkey import RootKey
from .chainkey import ChainKey
from ..protocol.ciphertextmessage import CiphertextMessage


class RatchetingSession:
    @staticmethod
    def initializeSession(sessionState, parameters):
        """
        :type sessionState: SessionState
        :type parameters: SymmetricAxolotlParameters
        """
        if RatchetingSession.isAlice(parameters.getOurBaseKey().getPublicKey(), parameters.getTheirBaseKey()):
            aliceParameters = AliceAxolotlParameters.newBuilder()
            aliceParameters.setOurBaseKey(parameters.getOurBaseKey()) \
                .setOurIdentityKey(parameters.getOurIdentityKey()) \
                .setTheirRatchetKey(parameters.getTheirRatchetKey()) \
                .setTheirIdentityKey(parameters.getTheirIdentityKey()) \
                .setTheirSignedPreKey(parameters.getTheirBaseKey()) \
                .setTheirOneTimePreKey(None)
            RatchetingSession.initializeSessionAsAlice(sessionState, aliceParameters.create())
        else:
            bobParameters = BobAxolotlParameters.newBuilder()
            bobParameters.setOurIdentityKey(parameters.getOurIdentityKey()) \
                .setOurRatchetKey(parameters.getOurRatchetKey()) \
                .setOurSignedPreKey(parameters.getOurBaseKey()) \
                .setOurOneTimePreKey(None) \
                .setTheirBaseKey(parameters.getTheirBaseKey()) \
                .setTheirIdentityKey(parameters.getTheirIdentityKey())
            RatchetingSession.initializeSessionAsBob(sessionState, bobParameters.create())

    @staticmethod
    def initializeSessionAsAlice(sessionState, parameters):
        """
        :type sessionState: SessionState
        :type parameters: AliceAxolotlParameters
        """
        sessionState.setSessionVersion(CiphertextMessage.CURRENT_VERSION)
        sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey())
        sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey())

        sendingRatchetKey = Curve.generateKeyPair()
        secrets = bytearray()

        secrets.extend(RatchetingSession.getDiscontinuityBytes())

        secrets.extend(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
                                                parameters.getOurIdentityKey().getPrivateKey()))
        secrets.extend(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(),
                                                parameters.getOurBaseKey().getPrivateKey()))
        secrets.extend(Curve.calculateAgreement(parameters.getTheirSignedPreKey(),
                                                parameters.getOurBaseKey().getPrivateKey()))

        if parameters.getTheirOneTimePreKey() is not None:
            secrets.extend(Curve.calculateAgreement(parameters.getTheirOneTimePreKey(),
                                                    parameters.getOurBaseKey().getPrivateKey()))

        derivedKeys = RatchetingSession.calculateDerivedKeys(secrets)
        sendingChain = derivedKeys.getRootKey().createChain(parameters.getTheirRatchetKey(), sendingRatchetKey)

        sessionState.addReceiverChain(parameters.getTheirRatchetKey(), derivedKeys.getChainKey())
        sessionState.setSenderChain(sendingRatchetKey, sendingChain[1])
        sessionState.setRootKey(sendingChain[0])

    @staticmethod
    def initializeSessionAsBob(sessionState, parameters):
        """
        :type sessionState: SessionState
        :type parameters: BobAxolotlParameters
        """
        sessionState.setSessionVersion(CiphertextMessage.CURRENT_VERSION)
        sessionState.setRemoteIdentityKey(parameters.getTheirIdentityKey())
        sessionState.setLocalIdentityKey(parameters.getOurIdentityKey().getPublicKey())

        secrets = bytearray()

        secrets.extend(RatchetingSession.getDiscontinuityBytes())

        secrets.extend(Curve.calculateAgreement(parameters.getTheirIdentityKey().getPublicKey(),
                                                parameters.getOurSignedPreKey().getPrivateKey()))

        secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(),
                                                parameters.getOurIdentityKey().getPrivateKey()))
        secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(),
                                                parameters.getOurSignedPreKey().getPrivateKey()))

        if parameters.getOurOneTimePreKey() is not None:
            secrets.extend(Curve.calculateAgreement(parameters.getTheirBaseKey(),
                                                    parameters.getOurOneTimePreKey().getPrivateKey()))

        derivedKeys = RatchetingSession.calculateDerivedKeys(secrets)
        sessionState.setSenderChain(parameters.getOurRatchetKey(), derivedKeys.getChainKey())
        sessionState.setRootKey(derivedKeys.getRootKey())

    @staticmethod
    def getDiscontinuityBytes():
        return bytearray([0xFF] * 32)

    @staticmethod
    def calculateDerivedKeys(masterSecret):
        kdf = HKDFv3()
        derivedSecretBytes = kdf.deriveSecrets(masterSecret,  bytearray("WhisperText".encode()), 64)
        derivedSecrets = ByteUtil.split(derivedSecretBytes, 32, 32)
        return RatchetingSession.DerivedKeys(RootKey(kdf, derivedSecrets[0]),
                                             ChainKey(kdf, derivedSecrets[1], 0))

    @staticmethod
    def isAlice(ourKey, theirKey):
        """
        :type ourKey: ECPublicKey
        :type theirKey: ECPublicKey
        """
        return ourKey < theirKey

    class DerivedKeys:
        def __init__(self, rootKey, chainKey):
            """
            :type rootKey: RootKey
            :type  chainKey: ChainKey
            """
            self.rootKey = rootKey
            self.chainKey = chainKey

        def getRootKey(self):
            return self.rootKey

        def getChainKey(self):
            return self.chainKey


================================================
FILE: axolotl/ratchet/rootkey.py
================================================
# -*- coding: utf-8 -*-

from ..ecc.curve import Curve
from ..kdf.derivedrootsecrets import DerivedRootSecrets
from .chainkey import ChainKey


class RootKey:
    def __init__(self, kdf, key):
        self.kdf = kdf
        self.key = key

    def getKeyBytes(self):
        return self.key

    def createChain(self, ECPublicKey_theirRatchetKey, ECKeyPair_ourRatchetKey):
        sharedSecret = Curve.calculateAgreement(ECPublicKey_theirRatchetKey, ECKeyPair_ourRatchetKey.getPrivateKey())
        derivedSecretBytes = self.kdf.deriveSecrets(sharedSecret,
                                                    "WhisperRatchet".encode(),
                                                    DerivedRootSecrets.SIZE,
                                                    salt=self.key)
        derivedSecrets = DerivedRootSecrets(derivedSecretBytes)
        newRootKey = RootKey(self.kdf, derivedSecrets.getRootKey())
        newChainKey = ChainKey(self.kdf, derivedSecrets.getChainKey(), 0)
        return (newRootKey, newChainKey)


================================================
FILE: axolotl/ratchet/symmetricaxolotlparameters.py
================================================
# -*- coding: utf-8 -*-


class SymmetricAxolotlParameters:
    def __init__(self, ourBaseKey, ourRatchetKey, ourIdentityKey, theirBaseKey,
                 theirRatchetKey, theirIdentityKey):
        """
        :type ourBaseKey: ECKeyPair
        :type ourRatchetKey: ECKeyPair
        :type ourIdentityKey: IdentityKeyPair
        :type theirBaseKey: ECPublicKey
        :type theirRatchetKey: ECKeyPair
        :type theirIdentityKey: IdentityKey
        """
        self.ourBaseKey = ourBaseKey
        self.ourIdentityKey = ourIdentityKey
        self.ourRatchetKey = ourRatchetKey
        self.theirRatchetKey = theirRatchetKey
        self.theirIdentityKey = theirIdentityKey
        self.theirBaseKey = theirBaseKey

        if ourBaseKey is None or ourIdentityKey is None or ourRatchetKey is None \
                or theirRatchetKey is None or theirIdentityKey is None or theirBaseKey is None:
            raise ValueError("Null value!")

    def getOurBaseKey(self):
        return self.ourBaseKey

    def getOurIdentityKey(self):
        return self.ourIdentityKey

    def getTheirRatchetKey(self):
        return self.theirRatchetKey

    def getTheirIdentityKey(self):
        return self.theirIdentityKey

    def getTheirBaseKey(self):
        return self.theirBaseKey

    def getOurRatchetKey(self):
        return self.ourRatchetKey

    @staticmethod
    def newBuilder():
        return SymmetricAxolotlParameters.Builder()

    class Builder:
        def __init__(self):
            self.ourIdentityKey = None
            self.ourBaseKey = None
            self.ourRatchetKey = None
            self.theirRatchetKey = None
            self.theirIdentityKey = None
            self.theirBaseKey = None

        def setOurIdentityKey(self, ourIdentityKey):
            self.ourIdentityKey = ourIdentityKey
            return self

        def setOurBaseKey(self, ourBaseKey):
            self.ourBaseKey = ourBaseKey
            return self

        def setOurRatchetKey(self, ourRatchetKey):
            self.ourRatchetKey = ourRatchetKey
            return self

        def setTheirRatchetKey(self, theirRatchetKey):
            self.theirRatchetKey = theirRatchetKey
            return self

        def setTheirIdentityKey(self, theirIdentityKey):
            self.theirIdentityKey = theirIdentityKey
            return self

        def setTheirBaseKey(self, theirBaseKey):
            self.theirBaseKey = theirBaseKey
            return self

        def create(self):
            return SymmetricAxolotlParameters(self.ourBaseKey, self.ourRatchetKey, self.ourIdentityKey,
                                              self.theirBaseKey, self.theirRatchetKey, self.theirIdentityKey)


================================================
FILE: axolotl/sessionbuilder.py
================================================
# -*- coding: utf-8 -*-

import logging

from .ecc.curve import Curve
from .ratchet.aliceaxolotlparameters import AliceAxolotlParameters
from .ratchet.bobaxolotlparamaters import BobAxolotlParameters
from .ratchet.symmetricaxolotlparameters import SymmetricAxolotlParameters
from .ratchet.ratchetingsession import RatchetingSession
from .invalidkeyexception import InvalidKeyException
from .invalidkeyidexception import InvalidKeyIdException
from .untrustedidentityexception import UntrustedIdentityException
from .protocol.keyexchangemessage import KeyExchangeMessage
from .protocol.ciphertextmessage import CiphertextMessage
from .statekeyexchangeexception import StaleKeyExchangeException
from .util.medium import Medium
from .util.keyhelper import KeyHelper


logger = logging.getLogger(__name__)


class SessionBuilder:
    def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, identityKeyStore, recepientId, deviceId):
        self.sessionStore = sessionStore
        self.preKeyStore = preKeyStore
        self.signedPreKeyStore = signedPreKeyStore
        self.identityKeyStore = identityKeyStore
        self.recipientId = recepientId
        self.deviceId = deviceId

    def process(self, sessionRecord, message):
        """
        :param sessionRecord:
        :param message:
        :type message: PreKeyWhisperMessage
        """

        theirIdentityKey = message.getIdentityKey()

        if not self.identityKeyStore.isTrustedIdentity(self.recipientId, theirIdentityKey):
            raise UntrustedIdentityException(self.recipientId, theirIdentityKey)

        unsignedPreKeyId = self.processV3(sessionRecord, message)

        self.identityKeyStore.saveIdentity(self.recipientId, theirIdentityKey)

        return unsignedPreKeyId

    def processV3(self, sessionRecord, message):
        """
        :param sessionRecord:
        :param message:
        :type message: PreKeyWhisperMessage
        :return:
        """

        if sessionRecord.hasSessionState(message.getMessageVersion(), message.getBaseKey().serialize()):
            logger.warn("We've already setup a session for this V3 message, letting bundled message fall through...")
            return None

        ourSignedPreKey = self.signedPreKeyStore.loadSignedPreKey(message.getSignedPreKeyId()).getKeyPair()
        parameters = BobAxolotlParameters.newBuilder()
        parameters.setTheirBaseKey(message.getBaseKey())\
            .setTheirIdentityKey(message.getIdentityKey())\
            .setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\
            .setOurSignedPreKey(ourSignedPreKey)\
            .setOurRatchetKey(ourSignedPreKey)

        if message.getPreKeyId() is not None:
            parameters.setOurOneTimePreKey(self.preKeyStore.loadPreKey(message.getPreKeyId()).getKeyPair())
        else:
            parameters.setOurOneTimePreKey(None)

        if not sessionRecord.isFresh():
            sessionRecord.archiveCurrentState()

        RatchetingSession.initializeSessionAsBob(sessionRecord.getSessionState(), parameters.create())
        sessionRecord.getSessionState().setLocalRegistrationId(self.identityKeyStore.getLocalRegistrationId())
        sessionRecord.getSessionState().setRemoteRegistrationId(message.getRegistrationId())
        sessionRecord.getSessionState().setAliceBaseKey(message.getBaseKey().serialize())

        if message.getPreKeyId() is not None and message.getPreKeyId() != Medium.MAX_VALUE:
            return message.getPreKeyId()
        else:
            return None

    def processPreKeyBundle(self, preKey):
        """
        :type preKey: PreKeyBundle
        """
        if not self.identityKeyStore.isTrustedIdentity(self.recipientId, preKey.getIdentityKey()):
            raise UntrustedIdentityException(self.recipientId, preKey.getIdentityKey())

        if preKey.getSignedPreKey() is not None and\
            not Curve.verifySignature(preKey.getIdentityKey().getPublicKey(),
                                      preKey.getSignedPreKey().serialize(),
                                      preKey.getSignedPreKeySignature()):
            raise InvalidKeyException("Invalid signature on device key!")

        if preKey.getSignedPreKey() is None:
            raise InvalidKeyException("No signed prekey!!")

        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)
        ourBaseKey = Curve.generateKeyPair()
        theirSignedPreKey = preKey.getSignedPreKey()
        theirOneTimePreKey = preKey.getPreKey()
        theirOneTimePreKeyId = preKey.getPreKeyId() if theirOneTimePreKey is not None else None

        parameters = AliceAxolotlParameters.newBuilder()

        parameters.setOurBaseKey(ourBaseKey)\
            .setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\
            .setTheirIdentityKey(preKey.getIdentityKey())\
            .setTheirSignedPreKey(theirSignedPreKey)\
            .setTheirRatchetKey(theirSignedPreKey)\
            .setTheirOneTimePreKey(theirOneTimePreKey)

        if not sessionRecord.isFresh():
            sessionRecord.archiveCurrentState()

        RatchetingSession.initializeSessionAsAlice(sessionRecord.getSessionState(), parameters.create())

        sessionRecord.getSessionState().setUnacknowledgedPreKeyMessage(theirOneTimePreKeyId,
                                                                       preKey.getSignedPreKeyId(),
                                                                       ourBaseKey.getPublicKey())
        sessionRecord.getSessionState().setLocalRegistrationId(self.identityKeyStore.getLocalRegistrationId())
        sessionRecord.getSessionState().setRemoteRegistrationId(preKey.getRegistrationId())
        sessionRecord.getSessionState().setAliceBaseKey(ourBaseKey.getPublicKey().serialize())
        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)
        self.identityKeyStore.saveIdentity(self.recipientId, preKey.getIdentityKey())

    def processKeyExchangeMessage(self, keyExchangeMessage):

        if not self.identityKeyStore.isTrustedIdentity(self.recipientId, keyExchangeMessage.getIdentityKey()):
            raise UntrustedIdentityException(self.recipientId, keyExchangeMessage.getIdentityKey())

        responseMessage = None

        if keyExchangeMessage.isInitiate():
            responseMessage = self.processInitiate(keyExchangeMessage)
        else:
            self.processResponse(keyExchangeMessage)

        return responseMessage

    def processInitiate(self, keyExchangeMessage):
        flags = KeyExchangeMessage.RESPONSE_FLAG
        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)

        if not Curve.verifySignature(
                keyExchangeMessage.getIdentityKey().getPublicKey(),
                keyExchangeMessage.getBaseKey().serialize(),
                keyExchangeMessage.getBaseKeySignature()):
            raise InvalidKeyException("Bad signature!")

        builder = SymmetricAxolotlParameters.newBuilder()
        if not sessionRecord.getSessionState().hasPendingKeyExchange():
            builder.setOurIdentityKey(self.identityKeyStore.getIdentityKeyPair())\
                .setOurBaseKey(Curve.generateKeyPair())\
                .setOurRatchetKey(Curve.generateKeyPair())
        else:
            builder.setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())\
                .setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())\
                .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey())
            flags |= KeyExchangeMessage.SIMULTAENOUS_INITIATE_FLAG

        builder.setTheirBaseKey(keyExchangeMessage.getBaseKey())\
            .setTheirRatchetKey(keyExchangeMessage.getRatchetKey())\
            .setTheirIdentityKey(keyExchangeMessage.getIdentityKey())

        parameters = builder.create()

        if not sessionRecord.isFresh():
            sessionRecord.archiveCurrentState()

        RatchetingSession.initializeSession(sessionRecord.getSessionState(), parameters)

        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)
        self.identityKeyStore.saveIdentity(self.recipientId, keyExchangeMessage.getIdentityKey())

        baseKeySignature = Curve.calculateSignature(parameters.getOurIdentityKey().getPrivateKey(),
                                                    parameters.getOurBaseKey().getPublicKey().serialize())

        return KeyExchangeMessage(sessionRecord.getSessionState().getSessionVersion(),
                                  keyExchangeMessage.getSequence(), flags,
                                  parameters.getOurBaseKey().getPublicKey(),
                                  baseKeySignature, parameters.getOurRatchetKey().getPublicKey(),
                                  parameters.getOurIdentityKey().getPublicKey())

    def processResponse(self, keyExchangeMessage):
        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)
        sessionState = sessionRecord.getSessionState()
        hasPendingKeyExchange = sessionState.hasPendingKeyExchange()
        isSimultaneousInitiateResponse = keyExchangeMessage.isResponseForSimultaneousInitiate()

        if not hasPendingKeyExchange \
                or sessionState.getPendingKeyExchangeSequence() != keyExchangeMessage.getSequence():
            logger.warn("No matching sequence for response. "
                        "Is simultaneous initiate response: %s" % isSimultaneousInitiateResponse)
            if not isSimultaneousInitiateResponse:
                raise StaleKeyExchangeException()
            else:
                return

        parameters = SymmetricAxolotlParameters.newBuilder()

        parameters.setOurBaseKey(sessionRecord.getSessionState().getPendingKeyExchangeBaseKey())\
            .setOurRatchetKey(sessionRecord.getSessionState().getPendingKeyExchangeRatchetKey())\
            .setOurIdentityKey(sessionRecord.getSessionState().getPendingKeyExchangeIdentityKey())\
            .setTheirBaseKey(keyExchangeMessage.getBaseKey())\
            .setTheirRatchetKey(keyExchangeMessage.getRatchetKey())\
            .setTheirIdentityKey(keyExchangeMessage.getIdentityKey())

        if not sessionRecord.isFresh():
            sessionRecord.archiveCurrentState()

        RatchetingSession.initializeSession(sessionRecord.getSessionState(), parameters.create())

        if not Curve.verifySignature(
                keyExchangeMessage.getIdentityKey().getPublicKey(),
                keyExchangeMessage.getBaseKey().serialize(),
                keyExchangeMessage.getBaseKeySignature()):
            raise InvalidKeyException("Base key signature doesn't match!")

        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)
        self.identityKeyStore.saveIdentity(self.recipientId, keyExchangeMessage.getIdentityKey())

    def processInitKeyExchangeMessage(self):
        try:
            sequence = KeyHelper.getRandomSequence(65534) + 1
            flags = KeyExchangeMessage.INITIATE_FLAG
            baseKey = Curve.generateKeyPair()
            ratchetKey = Curve.generateKeyPair()
            identityKey = self.identityKeyStore.getIdentityKeyPair()
            baseKeySignature = Curve.calculateSignature(identityKey.getPrivateKey(), baseKey.getPublicKey().serialize())
            sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)

            sessionRecord.getSessionState().setPendingKeyExchange(sequence, baseKey, ratchetKey, identityKey)
            self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)

            return KeyExchangeMessage(CiphertextMessage.CURRENT_VERSION, sequence, flags, baseKey.getPublicKey(), baseKeySignature,
                                      ratchetKey.getPublicKey(), identityKey.getPublicKey())
        except InvalidKeyException as e:
            raise AssertionError(e)


================================================
FILE: axolotl/sessioncipher.py
================================================
# -*- coding: utf-8 -*-

import sys

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import padding

from .ecc.curve import Curve
from .sessionbuilder import SessionBuilder
from .state.sessionstate import SessionState
from .protocol.whispermessage import WhisperMessage
from .protocol.prekeywhispermessage import PreKeyWhisperMessage
from .nosessionexception import NoSessionException
from .invalidmessageexception import InvalidMessageException
from .duplicatemessagexception import DuplicateMessageException

import  logging

logger = logging.getLogger(__name__)

class SessionCipher:
    def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, identityKeyStore, recepientId, deviceId):
        self.sessionStore = sessionStore
        self.preKeyStore = preKeyStore
        self.recipientId = recepientId
        self.deviceId = deviceId
        self.sessionBuilder = SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
                                             identityKeyStore, recepientId, deviceId)

    def encrypt(self, paddedMessage):
        """
        :type paddedMessage: bytes
        """
        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)
        sessionState = sessionRecord.getSessionState()
        chainKey = sessionState.getSenderChainKey()
        messageKeys = chainKey.getMessageKeys()
        senderEphemeral = sessionState.getSenderRatchetKey()
        previousCounter = sessionState.getPreviousCounter()
        sessionVersion = sessionState.getSessionVersion()

        ciphertextBody = self.getCiphertext(sessionVersion, messageKeys, paddedMessage)
        ciphertextMessage = WhisperMessage(sessionVersion, messageKeys.getMacKey(),
                                           senderEphemeral, chainKey.getIndex(),
                                           previousCounter, ciphertextBody,
                                           sessionState.getLocalIdentityKey(),
                                           sessionState.getRemoteIdentityKey())

        if sessionState.hasUnacknowledgedPreKeyMessage():
            items = sessionState.getUnacknowledgedPreKeyMessageItems()
            localRegistrationid = sessionState.getLocalRegistrationId()

            ciphertextMessage = PreKeyWhisperMessage(sessionVersion, localRegistrationid, items.getPreKeyId(),
                                                     items.getSignedPreKeyId(), items.getBaseKey(),
                                                     sessionState.getLocalIdentityKey(),
                                                     ciphertextMessage)
        sessionState.setSenderChainKey(chainKey.getNextChainKey())
        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)

        return ciphertextMessage

    def decryptMsg(self, ciphertext, textMsg=True):
        """
        :type ciphertext: WhisperMessage
        :type textMsg: Bool set this to False if you are decrypting bytes
                       instead of string
        """

        if not self.sessionStore.containsSession(self.recipientId, self.deviceId):
            raise NoSessionException("No session for: %s, %s" % (self.recipientId, self.deviceId))

        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)
        plaintext = self.decryptWithSessionRecord(sessionRecord, ciphertext)

        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)

        return plaintext

    def decryptPkmsg(self, ciphertext, textMsg=True):
        """
        :type ciphertext: PreKeyWhisperMessage
        """
        sessionRecord = self.sessionStore.loadSession(self.recipientId, self.deviceId)
        unsignedPreKeyId = self.sessionBuilder.process(sessionRecord, ciphertext)
        plaintext = self.decryptWithSessionRecord(sessionRecord, ciphertext.getWhisperMessage())

        # callback.handlePlaintext(plaintext)
        self.sessionStore.storeSession(self.recipientId, self.deviceId, sessionRecord)

        if unsignedPreKeyId is not None:
            self.preKeyStore.removePreKey(unsignedPreKeyId)

        return plaintext

    def decryptWithSessionRecord(self, sessionRecord, cipherText):
        """
        :type sessionRecord: SessionRecord
        :type cipherText: WhisperMessage
        """

        previousStates = sessionRecord.getPreviousSessionStates()
        exceptions = []
        try:
            sessionState = SessionState(sessionRecord.getSessionState())
            plaintext = self.decryptWithSessionState(sessionState, cipherText)
            sessionRecord.setState(sessionState)
            return plaintext
        except InvalidMessageException as e:
            exceptions.append(e)

        for i in range(0, len(previousStates)):
            previousState = previousStates[i]
            try:
                promotedState = SessionState(previousState)
                plaintext = self.decryptWithSessionState(promotedState, cipherText)
                previousStates.pop(i)
                sessionRecord.promoteState(promotedState)
                return plaintext
            except InvalidMessageException as e:
                exceptions.append(e)

        raise InvalidMessageException("No valid sessions", exceptions)

    def decryptWithSessionState(self, sessionState, ciphertextMessage):

        if not sessionState.hasSenderChain():
            raise InvalidMessageException("Uninitialized session!")

        if ciphertextMessage.getMessageVersion() != sessionState.getSessionVersion():
            raise InvalidMessageException("Message version %s, but session version %s" % (ciphertextMessage.getMessageVersion, sessionState.getSessionVersion()))

        messageVersion = ciphertextMessage.getMessageVersion()
        theirEphemeral = ciphertextMessage.getSenderRatchetKey()
        counter = ciphertextMessage.getCounter()
        chainKey = self.getOrCreateChainKey(sessionState, theirEphemeral)
        messageKeys = self.getOrCreateMessageKeys(sessionState, theirEphemeral, chainKey, counter)

        ciphertextMessage.verifyMac(messageVersion,
                                    sessionState.getRemoteIdentityKey(),
                                    sessionState.getLocalIdentityKey(),
                                    messageKeys.getMacKey())

        plaintext = self.getPlaintext(messageVersion, messageKeys, ciphertextMessage.getBody())
        sessionState.clearUnacknowledgedPreKeyMessage()

        return plaintext

    def getOrCreateChainKey(self, sessionState, ECPublickKey_theirEphemeral):
        theirEphemeral = ECPublickKey_theirEphemeral
        if sessionState.hasReceiverChain(theirEphemeral):
            return sessionState.getReceiverChainKey(theirEphemeral)
        else:
            rootKey = sessionState.getRootKey()
            ourEphemeral = sessionState.getSenderRatchetKeyPair()
            receiverChain = rootKey.createChain(theirEphemeral, ourEphemeral)
            ourNewEphemeral = Curve.generateKeyPair()
            senderChain = receiverChain[0].createChain(theirEphemeral, ourNewEphemeral)

            sessionState.setRootKey(senderChain[0])
            sessionState.addReceiverChain(theirEphemeral, receiverChain[1])
            sessionState.setPreviousCounter(max(sessionState.getSenderChainKey().getIndex() - 1, 0))
            sessionState.setSenderChain(ourNewEphemeral, senderChain[1])
            return receiverChain[1]

    def getOrCreateMessageKeys(self, sessionState, ECPublicKey_theirEphemeral, chainKey, counter):
        theirEphemeral = ECPublicKey_theirEphemeral
        if chainKey.getIndex() > counter:
            if sessionState.hasMessageKeys(theirEphemeral, counter):
                return sessionState.removeMessageKeys(theirEphemeral, counter)
            else:
                raise DuplicateMessageException("Received message with old counter: %s, %s" % (chainKey.getIndex(),
                                                                                               counter))

        if counter - chainKey.getIndex() > 2000:
            raise InvalidMessageException("Over 2000 messages into the future!")

        while chainKey.getIndex() < counter:
            messageKeys = chainKey.getMessageKeys()
            sessionState.setMessageKeys(theirEphemeral, messageKeys)
            chainKey = chainKey.getNextChainKey()

        sessionState.setReceiverChainKey(theirEphemeral, chainKey.getNextChainKey())
        return chainKey.getMessageKeys()

    def getCiphertext(self, version, messageKeys, plainText):
        """
        :type version: int
        :type messageKeys: MessageKeys
        :type  plainText: bytearray
        """
        cipher = self.getCipher(messageKeys.getCipherKey(), messageKeys.getIv())
        return cipher.encrypt(plainText)

    def getPlaintext(self, version, messageKeys, cipherText):
        cipher = self.getCipher(messageKeys.getCipherKey(), messageKeys.getIv())

        return cipher.decrypt(cipherText)

    def getCipher(self, key, iv):
        return AESCipher(key, iv)

class AESCipher:
    def __init__(self, key, iv):
        self.key = key
        self.iv = iv
        self.cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())

    def encrypt(self, raw):
        padder = padding.PKCS7(128).padder()
        rawPadded = padder.update(raw) + padder.finalize()

        encryptor = self.cipher.encryptor()
        try:
            return encryptor.update(rawPadded) + encryptor.finalize()
        except ValueError:
            raise

    def decrypt(self, enc):
        decryptor = self.cipher.decryptor()
        decrypted = decryptor.update(enc) + decryptor.finalize()
        unpadder = padding.PKCS7(128).unpadder()
        return unpadder.update(decrypted) + unpadder.finalize()


================================================
FILE: axolotl/state/__init__.py
================================================
# -*- coding: utf-8 -*-


================================================
FILE: axolotl/state/axolotlstore.py
================================================
# -*- coding: utf-8 -*-

import abc

from .identitykeystore import IdentityKeyStore
from .prekeystore import PreKeyStore
from .sessionstore import SessionStore
from .signedprekeystore import SignedPreKeyStore


class AxolotlStore(IdentityKeyStore, PreKeyStore, SignedPreKeyStore, SessionStore):
    __metaclass__ = abc.ABCMeta


================================================
FILE: axolotl/state/identitykeystore.py
================================================
# -*- coding: utf-8 -*-

import abc


class IdentityKeyStore(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def getIdentityKeyPair(self):
        pass

    @abc.abstractmethod
    def getLocalRegistrationId(self):
        pass

    @abc.abstractmethod
    def saveIdentity(self, recepientId, identityKey):
        pass

    @abc.abstractmethod
    def isTrustedIdentity(self, recepientId, identityKey):
        pass


================================================
FILE: axolotl/state/prekeybundle.py
================================================
# -*- cosing: utf-8 -*-


class PreKeyBundle:
    def __init__(self, registrationId, deviceId, preKeyId, ECPublicKey_preKeyPublic,
                 signedPreKeyId, ECPublicKey_signedPreKeyPublic, signedPreKeySignature,
                 identityKey):
        self.registrationId = registrationId
        self.deviceId = deviceId
        self.preKeyId = preKeyId
        self.preKeyPublic = ECPublicKey_preKeyPublic
        self.signedPreKeyId = signedPreKeyId
        self.signedPreKeyPublic = ECPublicKey_signedPreKeyPublic
        self.signedPreKeySignature = signedPreKeySignature
        self.identityKey = identityKey

    def getDeviceId(self):
        return self.deviceId

    def getPreKeyId(self):
        return self.preKeyId

    def getPreKey(self):
        return self.preKeyPublic

    def getSignedPreKeyId(self):
        return self.signedPreKeyId

    def getSignedPreKey(self):
        return self.signedPreKeyPublic

    def getSignedPreKeySignature(self):
        return self.signedPreKeySignature

    def getIdentityKey(self):
        return self.identityKey

    def getRegistrationId(self):
        return self.registrationId


================================================
FILE: axolotl/state/prekeyrecord.py
================================================
# -*- coding: utf-8 -*-

from .storageprotos_pb2 import PreKeyRecordStructure
from ..ecc.curve import Curve
from ..ecc.eckeypair import ECKeyPair


class PreKeyRecord:
    def __init__(self, _id=None, ecKeyPair=None, serialized=None):
        self.structure = PreKeyRecordStructure()
        if serialized:
            self.structure.ParseFromString(serialized)
        else:
            self.structure.id = _id
            self.structure.publicKey = ecKeyPair.getPublicKey().serialize()
            self.structure.privateKey = ecKeyPair.getPrivateKey().serialize()

    def getId(self):
        return self.structure.id

    def getKeyPair(self):
        publicKey = Curve.decodePoint(bytearray(self.structure.publicKey), 0)
        privateKey = Curve.decodePrivatePoint(bytearray(self.structure.privateKey))
        return ECKeyPair(publicKey, privateKey)

    def serialize(self):
        return self.structure.SerializeToString()


================================================
FILE: axolotl/state/prekeystore.py
================================================
# -*- coding: utf-8 -*-

import abc


class PreKeyStore(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def loadPreKey(self, preKeyId):
        pass

    @abc.abstractmethod
    def storePreKey(self, preKeyId, preKeyRecord):
        pass

    @abc.abstractmethod
    def containsPreKey(self, preKeyId):
        pass

    @abc.abstractmethod
    def removePreKey(self, preKeyId):
        pass


================================================
FILE: axolotl/state/sessionrecord.py
================================================
# -*- coding: utf-8 -*-

from . import storageprotos_pb2 as storageprotos
from .sessionstate import SessionState


class SessionRecord:
    ARCHIVED_STATES_MAX_LENGTH = 40

    def __init__(self, sessionState=None, serialized=None):
        """
        :type sessionState: SessionState
        :type serialized: str
        """
        self.previousStates = []
        if sessionState:
            self.sessionState = sessionState
            self.fresh = False
        elif serialized:
            record = storageprotos.RecordStructure()
            record.ParseFromString(serialized)
            self.sessionState = SessionState(record.currentSession)
            self.fresh = False
            for previousStructure in record.previousSessions:
                self.previousStates.append(SessionState(previousStructure))

        else:
            self.fresh = True
            self.sessionState = SessionState()

    def hasSessionState(self, version, aliceBaseKey):
        if self.sessionState.getSessionVersion() == version and aliceBaseKey == self.sessionState.getAliceBaseKey():
            return True

        for state in self.previousStates:
            if state.getSessionVersion() == version and aliceBaseKey == state.getAliceBaseKey():
                return True

        return False

    def getSessionState(self):
        return self.sessionState

    def getPreviousSessionStates(self):
        return self.previousStates

    def isFresh(self):
        return self.fresh

    def archiveCurrentState(self):
        self.promoteState(SessionState())

    def promoteState(self, promotedState):
        self.previousStates.insert(0, self.sessionState)
        self.sessionState = promotedState
        if len(self.previousStates) > self.__class__.ARCHIVED_STATES_MAX_LENGTH:
            self.previousStates.pop()

    def setState(self, sessionState):
        self.sessionState = sessionState

    def serialize(self):
        previousStructures = [previousState.getStructure() for previousState in self.previousStates]
        record = storageprotos.RecordStructure()
        record.currentSession.MergeFrom(self.sessionState.getStructure())
        record.previousSessions.extend(previousStructures)

        return record.SerializeToString()


================================================
FILE: axolotl/state/sessionstate.py
================================================
# -*- coding: utf-8 -*-

from . import storageprotos_pb2 as storageprotos
from ..identitykeypair import IdentityKey, IdentityKeyPair
from ..ratchet.rootkey import RootKey
from ..kdf.hkdf import HKDF
from ..ecc.curve import Curve
from ..ecc.eckeypair import ECKeyPair
from ..ratchet.chainkey import ChainKey
from ..kdf.messagekeys import MessageKeys


class SessionState:
    def __init__(self, session=None):
        if session is None:
            self.sessionStructure = storageprotos.SessionStructure()
        elif session.__class__ == SessionState:
            self.sessionStructure = storageprotos.SessionStructure()
            self.sessionStructure.CopyFrom(session.sessionStructure)
        else:
            self.sessionStructure = session

    def getStructure(self):
        return self.sessionStructure

    def getAliceBaseKey(self):
        return self.sessionStructure.aliceBaseKey

    def setAliceBaseKey(self, aliceBaseKey):
        self.sessionStructure.aliceBaseKey = aliceBaseKey

    def setSessionVersion(self, version):
        self.sessionStructure.sessionVersion = version

    def getSessionVersion(self):
        sessionVersion = self.sessionStructure.sessionVersion
        return 2 if sessionVersion == 0 else sessionVersion

    def setRemoteIdentityKey(self, identityKey):
        self.sessionStructure.remoteIdentityPublic = identityKey.serialize()

    def setLocalIdentityKey(self, identityKey):
        self.sessionStructure.localIdentityPublic = identityKey.serialize()

    def getRemoteIdentityKey(self):
        if self.sessionStructure.remoteIdentityPublic is None:
            return None
        return IdentityKey(self.sessionStructure.remoteIdentityPublic, 0)

    def getLocalIdentityKey(self):
        return IdentityKey(self.sessionStructure.localIdentityPublic, 0)

    def getPreviousCounter(self):
        return self.sessionStructure.previousCounter

    def setPreviousCounter(self, previousCounter):
        self.sessionStructure.previousCounter = previousCounter

    def getRootKey(self):
        return RootKey(HKDF.createFor(self.getSessionVersion()), self.sessionStructure.rootKey)

    def setRootKey(self, rootKey):
        self.sessionStructure.rootKey = rootKey.getKeyBytes()

    def getSenderRatchetKey(self):
        return Curve.decodePoint(bytearray(self.sessionStructure.senderChain.senderRatchetKey), 0)

    def getSenderRatchetKeyPair(self):
        publicKey = self.getSenderRatchetKey()
        privateKey = Curve.decodePrivatePoint(self.sessionStructure.senderChain.senderRatchetKeyPrivate)

        return ECKeyPair(publicKey, privateKey)

    def hasReceiverChain(self, ECPublickKey_senderEphemeral):
        return self.getReceiverChain(ECPublickKey_senderEphemeral) is not None

    def hasSenderChain(self):
        return self.sessionStructure.HasField("senderChain")

    def getReceiverChain(self, ECPublickKey_senderEphemeral):
        receiverChains = self.sessionStructure.receiverChains
        index = 0
        for receiverChain in receiverChains:
            chainSenderRatchetKey = Curve.decodePoint(bytearray(receiverChain.senderRatchetKey), 0)
            if chainSenderRatchetKey == ECPublickKey_senderEphemeral:
                return (receiverChain, index)

            index += 1

    def getReceiverChainKey(self, ECPublicKey_senderEphemeral):
        receiverChainAndIndex = self.getReceiverChain(ECPublicKey_senderEphemeral)
        receiverChain = receiverChainAndIndex[0]
        if receiverChain is None:
            return None

        return ChainKey(HKDF.createFor(self.getSessionVersion()),
                        receiverChain.chainKey.key,
                        receiverChain.chainKey.index)

    def addReceiverChain(self, ECPublickKey_senderRatchetKey, chainKey):
        senderRatchetKey = ECPublickKey_senderRatchetKey

        chain = storageprotos.SessionStructure.Chain()
        chain.senderRatchetKey = senderRatchetKey.serialize()
        chain.chainKey.key = chainKey.getKey()
        chain.chainKey.index = chainKey.getIndex()

        self.sessionStructure.receiverChains.extend([chain])

        if len(self.sessionStructure.receiverChains) > 5:
            del self.sessionStructure.receiverChains[0]

    def setSenderChain(self, ECKeyPair_senderRatchetKeyPair, chainKey):
        senderRatchetKeyPair = ECKeyPair_senderRatchetKeyPair

        # TODO: This is never used, maybe a bug?
        senderChain = storageprotos.SessionStructure.Chain()

        self.sessionStructure.senderChain.senderRatchetKey = senderRatchetKeyPair.getPublicKey().serialize()
        self.sessionStructure.senderChain.senderRatchetKeyPrivate = senderRatchetKeyPair.getPrivateKey().serialize()
        self.sessionStructure.senderChain.chainKey.key = chainKey.key
        self.sessionStructure.senderChain.chainKey.index = chainKey.index

    def getSenderChainKey(self):
        chainKeyStructure = self.sessionStructure.senderChain.chainKey
        return ChainKey(HKDF.createFor(self.getSessionVersion()),
                        chainKeyStructure.key, chainKeyStructure.index)

    def setSenderChainKey(self, ChainKey_nextChainKey):
        nextChainKey = ChainKey_nextChainKey

        self.sessionStructure.senderChain.chainKey.key = nextChainKey.getKey()
        self.sessionStructure.senderChain.chainKey.index = nextChainKey.getIndex()

    def hasMessageKeys(self, ECPublickKey_senderEphemeral, counter):
        senderEphemeral = ECPublickKey_senderEphemeral
        chainAndIndex = self.getReceiverChain(senderEphemeral)
        chain = chainAndIndex[0]
        if chain is None:
            return False

        messageKeyList = chain.messageKeys
        for messageKey in messageKeyList:
            if messageKey.index == counter:
                return True

        return False

    def removeMessageKeys(self, ECPublicKey_senderEphemeral, counter):
        senderEphemeral = ECPublicKey_senderEphemeral
        chainAndIndex = self.getReceiverChain(senderEphemeral)
        chain = chainAndIndex[0]
        if chain is None:
            return None

        messageKeyList = chain.messageKeys
        result = None

        for i in range(0, len(messageKeyList)):
            messageKey = messageKeyList[i]
            if messageKey.index == counter:
                result = MessageKeys(messageKey.cipherKey, messageKey.macKey, messageKey.iv, messageKey.index)
                del messageKeyList[i]
                break

        self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain)

        return result

    def setMessageKeys(self, ECPublicKey_senderEphemeral, messageKeys):
        senderEphemeral = ECPublicKey_senderEphemeral
        chainAndIndex = self.getReceiverChain(senderEphemeral)
        chain = chainAndIndex[0]
        messageKeyStructure = chain.messageKeys.add()  # storageprotos.SessionStructure.Chain.MessageKey()
        messageKeyStructure.cipherKey = messageKeys.getCipherKey()
        messageKeyStructure.macKey = messageKeys.getMacKey()
        messageKeyStructure.index = messageKeys.getCounter()
        messageKeyStructure.iv = messageKeys.getIv()

        # chain.messageKeys.append(messageKeyStructure)

        self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain)

    def setReceiverChainKey(self, ECPublicKey_senderEphemeral, chainKey):
        senderEphemeral = ECPublicKey_senderEphemeral
        chainAndIndex = self.getReceiverChain(senderEphemeral)
        chain = chainAndIndex[0]
        chain.chainKey.key = chainKey.getKey()
        chain.chainKey.index = chainKey.getIndex()

        # self.sessionStructure.receiverChains[chainAndIndex[1]].ClearField()
        self.sessionStructure.receiverChains[chainAndIndex[1]].CopyFrom(chain)

    def setPendingKeyExchange(self, sequence, ourBaseKey, ourRatchetKey, ourIdentityKey):
        """
        :type sequence: int
        :type ourBaseKey: ECKeyPair
        :type ourRatchetKey: ECKeyPair
        :type  ourIdentityKey: IdentityKeyPair
        """
        structure = self.sessionStructure.PendingKeyExchange()
        structure.sequence = sequence
        structure.localBaseKey = ourBaseKey.getPublicKey().serialize()
        structure.localBaseKeyPrivate = ourBaseKey.getPrivateKey().serialize()
        structure.localRatchetKey = ourRatchetKey.getPublicKey().serialize()
        structure.localRatchetKeyPrivate = ourRatchetKey.getPrivateKey().serialize()
        structure.localIdentityKey = ourIdentityKey.getPublicKey().serialize()
        structure.localIdentityKeyPrivate = ourIdentityKey.getPrivateKey().serialize()

        self.sessionStructure.pendingKeyExchange.MergeFrom(structure)

    def getPendingKeyExchangeSequence(self):
        return self.sessionStructure.pendingKeyExchange.sequence

    def getPendingKeyExchangeBaseKey(self):
        publicKey = Curve.decodePoint(bytearray(self.sessionStructure.pendingKeyExchange.localBaseKey), 0)
        privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localBaseKeyPrivate)
        return ECKeyPair(publicKey, privateKey)

    def getPendingKeyExchangeRatchetKey(self):
        publicKey = Curve.decodePoint(bytearray(self.sessionStructure.pendingKeyExchange.localRatchetKey), 0)
        privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localRatchetKeyPrivate)
        return ECKeyPair(publicKey, privateKey)

    def getPendingKeyExchangeIdentityKey(self):
        publicKey = IdentityKey(bytearray(self.sessionStructure.pendingKeyExchange.localIdentityKey), 0)

        privateKey = Curve.decodePrivatePoint(self.sessionStructure.pendingKeyExchange.localIdentityKeyPrivate)
        return IdentityKeyPair(publicKey, privateKey)

    def hasPendingKeyExchange(self):
        return self.sessionStructure.HasField("pendingKeyExchange")

    def setUnacknowledgedPreKeyMessage(self, preKeyId, signedPreKeyId, baseKey):
        """
        :type preKeyId: int
        :type signedPreKeyId: int
        :type baseKey: ECPublicKey
        """
        self.sessionStructure.pendingPreKey.signedPreKeyId = signedPreKeyId
        self.sessionStructure.pendingPreKey.baseKey = baseKey.serialize()

        if preKeyId is not None:
            self.sessionStructure.pendingPreKey.preKeyId = preKeyId

    def hasUnacknowledgedPreKeyMessage(self):
        return self.sessionStructure.HasField("pendingPreKey")

    def getUnacknowledgedPreKeyMessageItems(self):
        preKeyId = None
        if self.sessionStructure.pendingPreKey.HasField("preKeyId"):
            preKeyId = self.sessionStructure.pendingPreKey.preKeyId

        return SessionState.UnacknowledgedPreKeyMessageItems(preKeyId,
                                                             self.sessionStructure.pendingPreKey.signedPreKeyId,
                                                             Curve.decodePoint(bytearray(self.sessionStructure.pendingPreKey.baseKey), 0))

    def clearUnacknowledgedPreKeyMessage(self):
        self.sessionStructure.ClearField("pendingPreKey")

    def setRemoteRegistrationId(self, registrationId):
        self.sessionStructure.remoteRegistrationId = registrationId

    def getRemoteRegistrationId(self, registrationId):
        return self.sessionStructure.remoteRegistrationId

    def setLocalRegistrationId(self, registrationId):
        self.sessionStructure.localRegistrationId = registrationId

    def getLocalRegistrationId(self):
        return self.sessionStructure.localRegistrationId

    def serialize(self):
        return self.sessionStructure.SerializeToString()

    class UnacknowledgedPreKeyMessageItems:
        def __init__(self, preKeyId, signedPreKeyId, baseKey):
            """
            :type preKeyId: int
            :type signedPreKeyId: int
            :type baseKey: ECPublicKey
            """
            self.preKeyId = preKeyId
            self.signedPreKeyId = signedPreKeyId
            self.baseKey = baseKey

        def getPreKeyId(self):
            return self.preKeyId

        def getSignedPreKeyId(self):
            return self.signedPreKeyId

        def getBaseKey(self):
            return self.baseKey


================================================
FILE: axolotl/state/sessionstore.py
================================================
# -*- cosing: utf-8 -*-

import abc


class SessionStore(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def loadSession(self, recepientId, deviceId):
        pass

    @abc.abstractmethod
    def getSubDeviceSessions(self, recepientId):
        pass

    @abc.abstractmethod
    def storeSession(self, recepientId, deviceId, sessionRecord):
        pass

    @abc.abstractmethod
    def containsSession(self, recepientId, deviceId):
        pass

    @abc.abstractmethod
    def deleteSession(self, recepientId, deviceId):
        pass

    @abc.abstractmethod
    def deleteAllSessions(self, recepientId):
        pass


================================================
FILE: axolotl/state/signedprekeyrecord.py
================================================
# -*- coding; utf-8 -*-

from .storageprotos_pb2 import SignedPreKeyRecordStructure
from ..ecc.curve import Curve
from ..ecc.eckeypair import ECKeyPair


class SignedPreKeyRecord:
    def __init__(self, _id=None, timestamp=None, ecKeyPair=None, signature=None, serialized=None):
        self.structure = SignedPreKeyRecordStructure()
        if serialized:
            self.structure.ParseFromString(serialized)
        else:
            self.structure.id = _id
            self.structure.publicKey = ecKeyPair.getPublicKey().serialize()
            self.structure.privateKey = ecKeyPair.getPrivateKey().serialize()
            self.structure.signature = signature
            self.structure.timestamp = timestamp

    def getId(self):
        return self.structure.id

    def getTimestamp(self):
        return self.structure.timestamp

    def getKeyPair(self):
        publicKey = Curve.decodePoint(bytearray(self.structure.publicKey), 0)
        privateKey = Curve.decodePrivatePoint(bytearray(self.structure.privateKey))

        return ECKeyPair(publicKey, privateKey)

    def getSignature(self):
        return self.structure.signature

    def serialize(self):
        return self.structure.SerializeToString()


================================================
FILE: axolotl/state/signedprekeystore.py
================================================
# -*- coding: utf-8 -*-

import abc


class SignedPreKeyStore(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def loadSignedPreKey(self, signedPreKeyId):
        pass

    @abc.abstractmethod
    def loadSignedPreKeys(self):
        pass

    @abc.abstractmethod
    def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord):
        pass

    @abc.abstractmethod
    def containsSignedPreKey(self, signedPreKeyId):
        pass

    @abc.abstractmethod
    def removeSignedPreKey(self, signedPreKeyId):
        pass


================================================
FILE: axolotl/state/storageprotos_pb2.py
================================================
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: LocalStorageProtocol.proto

import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)

_sym_db = _symbol_database.Default()




DESCRIPTOR = _descriptor.FileDescriptor(
  name='LocalStorageProtocol.proto',
  package='textsecure',
  serialized_pb=_b('\n\x1aLocalStorageProtocol.proto\x12\ntextsecure\"\xd3\x08\n\x10SessionStructure\x12\x16\n\x0esessionVersion\x18\x01 \x01(\r\x12\x1b\n\x13localIdentityPublic\x18\x02 \x01(\x0c\x12\x1c\n\x14remoteIdentityPublic\x18\x03 \x01(\x0c\x12\x0f\n\x07rootKey\x18\x04 \x01(\x0c\x12\x17\n\x0fpreviousCounter\x18\x05 \x01(\r\x12\x37\n\x0bsenderChain\x18\x06 \x01(\x0b\x32\".textsecure.SessionStructure.Chain\x12:\n\x0ereceiverChains\x18\x07 \x03(\x0b\x32\".textsecure.SessionStructure.Chain\x12K\n\x12pendingKeyExchange\x18\x08 \x01(\x0b\x32/.textsecure.SessionStructure.PendingKeyExchange\x12\x41\n\rpendingPreKey\x18\t \x01(\x0b\x32*.textsecure.SessionStructure.PendingPreKey\x12\x1c\n\x14remoteRegistrationId\x18\n \x01(\r\x12\x1b\n\x13localRegistrationId\x18\x0b \x01(\r\x12\x14\n\x0cneedsRefresh\x18\x0c \x01(\x08\x12\x14\n\x0c\x61liceBaseKey\x18\r \x01(\x0c\x1a\xb9\x02\n\x05\x43hain\x12\x18\n\x10senderRatchetKey\x18\x01 \x01(\x0c\x12\x1f\n\x17senderRatchetKeyPrivate\x18\x02 \x01(\x0c\x12=\n\x08\x63hainKey\x18\x03 \x01(\x0b\x32+.textsecure.SessionStructure.Chain.ChainKey\x12\x42\n\x0bmessageKeys\x18\x04 \x03(\x0b\x32-.textsecure.SessionStructure.Chain.MessageKey\x1a&\n\x08\x43hainKey\x12\r\n\x05index\x18\x01 \x01(\r\x12\x0b\n\x03key\x18\x02 \x01(\x0c\x1aJ\n\nMessageKey\x12\r\n\x05index\x18\x01 \x01(\r\x12\x11\n\tcipherKey\x18\x02 \x01(\x0c\x12\x0e\n\x06macKey\x18\x03 \x01(\x0c\x12\n\n\x02iv\x18\x04 \x01(\x0c\x1a\xcd\x01\n\x12PendingKeyExchange\x12\x10\n\x08sequence\x18\x01 \x01(\r\x12\x14\n\x0clocalBaseKey\x18\x02 \x01(\x0c\x12\x1b\n\x13localBaseKeyPrivate\x18\x03 \x01(\x0c\x12\x17\n\x0flocalRatchetKey\x18\x04 \x01(\x0c\x12\x1e\n\x16localRatchetKeyPrivate\x18\x05 \x01(\x0c\x12\x18\n\x10localIdentityKey\x18\x07 \x01(\x0c\x12\x1f\n\x17localIdentityKeyPrivate\x18\x08 \x01(\x0c\x1aJ\n\rPendingPreKey\x12\x10\n\x08preKeyId\x18\x01 \x01(\r\x12\x16\n\x0esignedPreKeyId\x18\x03 \x01(\x05\x12\x0f\n\x07\x62\x61seKey\x18\x02 \x01(\x0c\"\x7f\n\x0fRecordStructure\x12\x34\n\x0e\x63urrentSession\x18\x01 \x01(\x0b\x32\x1c.textsecure.SessionStructure\x12\x36\n\x10previousSessions\x18\x02 \x03(\x0b\x32\x1c.textsecure.SessionStructure\"J\n\x15PreKeyRecordStructure\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tpublicKey\x18\x02 \x01(\x0c\x12\x12\n\nprivateKey\x18\x03 \x01(\x0c\"v\n\x1bSignedPreKeyRecordStructure\x12\n\n\x02id\x18\x01 \x01(\r\x12\x11\n\tpublicKey\x18\x02 \x01(\x0c\x12\x12\n\nprivateKey\x18\x03 \x01(\x0c\x12\x11\n\tsignature\x18\x04 \x01(\x0c\x12\x11\n\ttimestamp\x18\x05 \x01(\x06\"A\n\x18IdentityKeyPairStructure\x12\x11\n\tpublicKey\x18\x01 \x01(\x0c\x12\x12\n\nprivateKey\x18\x02 \x01(\x0c\"\xb8\x03\n\x17SenderKeyStateStructure\x12\x13\n\x0bsenderKeyId\x18\x01 \x01(\r\x12J\n\x0esenderChainKey\x18\x02 \x01(\x0b\x32\x32.textsecure.SenderKeyStateStructure.SenderChainKey\x12N\n\x10senderSigningKey\x18\x03 \x01(\x0b\x32\x34.textsecure.SenderKeyStateStructure.SenderSigningKey\x12O\n\x11senderMessageKeys\x18\x04 \x03(\x0b\x32\x34.textsecure.SenderKeyStateStructure.SenderMessageKey\x1a\x31\n\x0eSenderChainKey\x12\x11\n\titeration\x18\x01 \x01(\r\x12\x0c\n\x04seed\x18\x02 \x01(\x0c\x1a\x33\n\x10SenderMessageKey\x12\x11\n\titeration\x18\x01 \x01(\r\x12\x0c\n\x04seed\x18\x02 \x01(\x0c\x1a\x33\n\x10SenderSigningKey\x12\x0e\n\x06public\x18\x01 \x01(\x0c\x12\x0f\n\x07private\x18\x02 \x01(\x0c\"X\n\x18SenderKeyRecordStructure\x12<\n\x0fsenderKeyStates\x18\x01 \x03(\x0b\x32#.textsecure.SenderKeyStateStructureB4\n#org.whispersystems.libaxolotl.stateB\rStorageProtos')
)
_sym_db.RegisterFileDescriptor(DESCRIPTOR)




_SESSIONSTRUCTURE_CHAIN_CHAINKEY = _descriptor.Descriptor(
  name='ChainKey',
  full_name='textsecure.SessionStructure.Chain.ChainKey',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='index', full_name='textsecure.SessionStructure.Chain.ChainKey.index', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='key', full_name='textsecure.SessionStructure.Chain.ChainKey.key', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=752,
  serialized_end=790,
)

_SESSIONSTRUCTURE_CHAIN_MESSAGEKEY = _descriptor.Descriptor(
  name='MessageKey',
  full_name='textsecure.SessionStructure.Chain.MessageKey',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='index', full_name='textsecure.SessionStructure.Chain.MessageKey.index', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='cipherKey', full_name='textsecure.SessionStructure.Chain.MessageKey.cipherKey', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='macKey', full_name='textsecure.SessionStructure.Chain.MessageKey.macKey', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='iv', full_name='textsecure.SessionStructure.Chain.MessageKey.iv', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=792,
  serialized_end=866,
)

_SESSIONSTRUCTURE_CHAIN = _descriptor.Descriptor(
  name='Chain',
  full_name='textsecure.SessionStructure.Chain',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='senderRatchetKey', full_name='textsecure.SessionStructure.Chain.senderRatchetKey', index=0,
      number=1, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='senderRatchetKeyPrivate', full_name='textsecure.SessionStructure.Chain.senderRatchetKeyPrivate', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='chainKey', full_name='textsecure.SessionStructure.Chain.chainKey', index=2,
      number=3, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='messageKeys', full_name='textsecure.SessionStructure.Chain.messageKeys', index=3,
      number=4, type=11, cpp_type=10, label=3,
      has_default_value=False, default_value=[],
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[_SESSIONSTRUCTURE_CHAIN_CHAINKEY, _SESSIONSTRUCTURE_CHAIN_MESSAGEKEY, ],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=553,
  serialized_end=866,
)

_SESSIONSTRUCTURE_PENDINGKEYEXCHANGE = _descriptor.Descriptor(
  name='PendingKeyExchange',
  full_name='textsecure.SessionStructure.PendingKeyExchange',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='sequence', full_name='textsecure.SessionStructure.PendingKeyExchange.sequence', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localBaseKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localBaseKey', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localBaseKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localBaseKeyPrivate', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localRatchetKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localRatchetKey', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localRatchetKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localRatchetKeyPrivate', index=4,
      number=5, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localIdentityKey', full_name='textsecure.SessionStructure.PendingKeyExchange.localIdentityKey', index=5,
      number=7, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localIdentityKeyPrivate', full_name='textsecure.SessionStructure.PendingKeyExchange.localIdentityKeyPrivate', index=6,
      number=8, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=869,
  serialized_end=1074,
)

_SESSIONSTRUCTURE_PENDINGPREKEY = _descriptor.Descriptor(
  name='PendingPreKey',
  full_name='textsecure.SessionStructure.PendingPreKey',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='preKeyId', full_name='textsecure.SessionStructure.PendingPreKey.preKeyId', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='signedPreKeyId', full_name='textsecure.SessionStructure.PendingPreKey.signedPreKeyId', index=1,
      number=3, type=5, cpp_type=1, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='baseKey', full_name='textsecure.SessionStructure.PendingPreKey.baseKey', index=2,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=1076,
  serialized_end=1150,
)

_SESSIONSTRUCTURE = _descriptor.Descriptor(
  name='SessionStructure',
  full_name='textsecure.SessionStructure',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='sessionVersion', full_name='textsecure.SessionStructure.sessionVersion', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localIdentityPublic', full_name='textsecure.SessionStructure.localIdentityPublic', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='remoteIdentityPublic', full_name='textsecure.SessionStructure.remoteIdentityPublic', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='rootKey', full_name='textsecure.SessionStructure.rootKey', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='previousCounter', full_name='textsecure.SessionStructure.previousCounter', index=4,
      number=5, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='senderChain', full_name='textsecure.SessionStructure.senderChain', index=5,
      number=6, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='receiverChains', full_name='textsecure.SessionStructure.receiverChains', index=6,
      number=7, type=11, cpp_type=10, label=3,
      has_default_value=False, default_value=[],
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='pendingKeyExchange', full_name='textsecure.SessionStructure.pendingKeyExchange', index=7,
      number=8, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='pendingPreKey', full_name='textsecure.SessionStructure.pendingPreKey', index=8,
      number=9, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='remoteRegistrationId', full_name='textsecure.SessionStructure.remoteRegistrationId', index=9,
      number=10, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='localRegistrationId', full_name='textsecure.SessionStructure.localRegistrationId', index=10,
      number=11, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='needsRefresh', full_name='textsecure.SessionStructure.needsRefresh', index=11,
      number=12, type=8, cpp_type=7, label=1,
      has_default_value=False, default_value=False,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='aliceBaseKey', full_name='textsecure.SessionStructure.aliceBaseKey', index=12,
      number=13, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[_SESSIONSTRUCTURE_CHAIN, _SESSIONSTRUCTURE_PENDINGKEYEXCHANGE, _SESSIONSTRUCTURE_PENDINGPREKEY, ],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=43,
  serialized_end=1150,
)


_RECORDSTRUCTURE = _descriptor.Descriptor(
  name='RecordStructure',
  full_name='textsecure.RecordStructure',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='currentSession', full_name='textsecure.RecordStructure.currentSession', index=0,
      number=1, type=11, cpp_type=10, label=1,
      has_default_value=False, default_value=None,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='previousSessions', full_name='textsecure.RecordStructure.previousSessions', index=1,
      number=2, type=11, cpp_type=10, label=3,
      has_default_value=False, default_value=[],
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=1152,
  serialized_end=1279,
)


_PREKEYRECORDSTRUCTURE = _descriptor.Descriptor(
  name='PreKeyRecordStructure',
  full_name='textsecure.PreKeyRecordStructure',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='id', full_name='textsecure.PreKeyRecordStructure.id', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='publicKey', full_name='textsecure.PreKeyRecordStructure.publicKey', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='privateKey', full_name='textsecure.PreKeyRecordStructure.privateKey', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=1281,
  serialized_end=1355,
)


_SIGNEDPREKEYRECORDSTRUCTURE = _descriptor.Descriptor(
  name='SignedPreKeyRecordStructure',
  full_name='textsecure.SignedPreKeyRecordStructure',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='id', full_name='textsecure.SignedPreKeyRecordStructure.id', index=0,
      number=1, type=13, cpp_type=3, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='publicKey', full_name='textsecure.SignedPreKeyRecordStructure.publicKey', index=1,
      number=2, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='privateKey', full_name='textsecure.SignedPreKeyRecordStructure.privateKey', index=2,
      number=3, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='signature', full_name='textsecure.SignedPreKeyRecordStructure.signature', index=3,
      number=4, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descriptor.FieldDescriptor(
      name='timestamp', full_name='textsecure.SignedPreKeyRecordStructure.timestamp', index=4,
      number=5, type=6, cpp_type=4, label=1,
      has_default_value=False, default_value=0,
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
  ],
  extensions=[
  ],
  nested_types=[],
  enum_types=[
  ],
  options=None,
  is_extendable=False,
  extension_ranges=[],
  oneofs=[
  ],
  serialized_start=1357,
  serialized_end=1475,
)


_IDENTITYKEYPAIRSTRUCTURE = _descriptor.Descriptor(
  name='IdentityKeyPairStructure',
  full_name='textsecure.IdentityKeyPairStructure',
  filename=None,
  file=DESCRIPTOR,
  containing_type=None,
  fields=[
    _descriptor.FieldDescriptor(
      name='publicKey', full_name='textsecure.IdentityKeyPairStructure.publicKey', index=0,
      number=1, type=12, cpp_type=9, label=1,
      has_default_value=False, default_value=_b(""),
      message_type=None, enum_type=None, containing_type=None,
      is_extension=False, extension_scope=None,
      options=None),
    _descr
Download .txt
gitextract_vf0yghin/

├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── axolotl/
│   ├── __init__.py
│   ├── axolotladdress.py
│   ├── duplicatemessagexception.py
│   ├── ecc/
│   │   ├── __init__.py
│   │   ├── curve.py
│   │   ├── djbec.py
│   │   ├── ec.py
│   │   └── eckeypair.py
│   ├── groups/
│   │   ├── __init__.py
│   │   ├── groupcipher.py
│   │   ├── groupsessionbuilder.py
│   │   ├── ratchet/
│   │   │   ├── __init__.py
│   │   │   ├── senderchainkey.py
│   │   │   └── sendermessagekey.py
│   │   ├── senderkeyname.py
│   │   └── state/
│   │       ├── __init__.py
│   │       ├── senderkeyrecord.py
│   │       ├── senderkeystate.py
│   │       └── senderkeystore.py
│   ├── identitykey.py
│   ├── identitykeypair.py
│   ├── invalidkeyexception.py
│   ├── invalidkeyidexception.py
│   ├── invalidmessageexception.py
│   ├── invalidversionexception.py
│   ├── kdf/
│   │   ├── __init__.py
│   │   ├── derivedmessagesecrets.py
│   │   ├── derivedrootsecrets.py
│   │   ├── hkdf.py
│   │   ├── hkdfv2.py
│   │   ├── hkdfv3.py
│   │   └── messagekeys.py
│   ├── legacymessageexception.py
│   ├── nosessionexception.py
│   ├── protobuf/
│   │   ├── LocalStorageProtocol.proto
│   │   └── WhisperTextProtocol.proto
│   ├── protocol/
│   │   ├── __init__.py
│   │   ├── ciphertextmessage.py
│   │   ├── keyexchangemessage.py
│   │   ├── prekeywhispermessage.py
│   │   ├── senderkeydistributionmessage.py
│   │   ├── senderkeymessage.py
│   │   ├── whispermessage.py
│   │   └── whisperprotos_pb2.py
│   ├── ratchet/
│   │   ├── __init__.py
│   │   ├── aliceaxolotlparameters.py
│   │   ├── bobaxolotlparamaters.py
│   │   ├── chainkey.py
│   │   ├── ratchetingsession.py
│   │   ├── rootkey.py
│   │   └── symmetricaxolotlparameters.py
│   ├── sessionbuilder.py
│   ├── sessioncipher.py
│   ├── state/
│   │   ├── __init__.py
│   │   ├── axolotlstore.py
│   │   ├── identitykeystore.py
│   │   ├── prekeybundle.py
│   │   ├── prekeyrecord.py
│   │   ├── prekeystore.py
│   │   ├── sessionrecord.py
│   │   ├── sessionstate.py
│   │   ├── sessionstore.py
│   │   ├── signedprekeyrecord.py
│   │   ├── signedprekeystore.py
│   │   └── storageprotos_pb2.py
│   ├── statekeyexchangeexception.py
│   ├── tests/
│   │   ├── __init__.py
│   │   ├── groups/
│   │   │   ├── __init__.py
│   │   │   ├── inmemorysenderkeystore.py
│   │   │   └── test_groupcipher.py
│   │   ├── inmemoryaxolotlstore.py
│   │   ├── inmemoryidentitykeystore.py
│   │   ├── inmemoryprekeystore.py
│   │   ├── inmemorysessionstore.py
│   │   ├── inmemorysignedprekeystore.py
│   │   ├── kdf/
│   │   │   ├── __init__.py
│   │   │   └── test_hkdf.py
│   │   ├── ratchet/
│   │   │   ├── __init__.py
│   │   │   ├── test_chainkey.py
│   │   │   ├── test_ratchetingsession.py
│   │   │   └── test_rootkey.py
│   │   ├── test_sessionbuilder.py
│   │   ├── test_sessioncipher.py
│   │   ├── test_sigs.py
│   │   └── util/
│   │       ├── __init__.py
│   │       └── test_byteutil.py
│   ├── untrustedidentityexception.py
│   └── util/
│       ├── __init__.py
│       ├── byteutil.py
│       ├── hexutil.py
│       ├── keyhelper.py
│       └── medium.py
├── setup.py
└── tox.ini
Download .txt
SYMBOL INDEX (511 symbols across 73 files)

FILE: axolotl/axolotladdress.py
  class AxolotlAddress (line 1) | class AxolotlAddress(object):
    method __init__ (line 2) | def __init__(self, name, deviceId):
    method getName (line 6) | def getName(self):
    method getDeviceId (line 9) | def getDeviceId(self):
    method __str__ (line 12) | def __str__(self):
    method __eq__ (line 15) | def __eq__(self, other):
    method __hash__ (line 24) | def __hash__(self):

FILE: axolotl/duplicatemessagexception.py
  class DuplicateMessageException (line 4) | class DuplicateMessageException(Exception):

FILE: axolotl/ecc/curve.py
  class Curve (line 11) | class Curve:
    method generatePrivateKey (line 16) | def generatePrivateKey():
    method generatePublicKey (line 21) | def generatePublicKey(privateKey):
    method generateKeyPair (line 25) | def generateKeyPair():
    method decodePoint (line 33) | def decodePoint(_bytes, offset=0):
    method decodePrivatePoint (line 48) | def decodePrivatePoint(_bytes):
    method calculateAgreement (line 53) | def calculateAgreement(publicKey, privateKey):
    method verifySignature (line 67) | def verifySignature(ecPublicSigningKey, message, signature):
    method calculateSignature (line 81) | def calculateSignature(privateSigningKey, message):

FILE: axolotl/ecc/djbec.py
  class DjbECPublicKey (line 9) | class DjbECPublicKey(ECPublicKey):
    method __init__ (line 11) | def __init__(self, publicKey):
    method serialize (line 14) | def serialize(self):
    method getType (line 20) | def getType(self):
    method getPublicKey (line 25) | def getPublicKey(self):
    method __eq__ (line 28) | def __eq__(self, other):
    method __lt__ (line 31) | def __lt__(self, other):
    method __cmp__ (line 37) | def __cmp__(self, other):
  class DjbECPrivateKey (line 49) | class DjbECPrivateKey(ECPrivateKey):
    method __init__ (line 50) | def __init__(self, privateKey):
    method getType (line 53) | def getType(self):
    method getPrivateKey (line 58) | def getPrivateKey(self):
    method serialize (line 61) | def serialize(self):
    method __eq__ (line 64) | def __eq__(self, other):

FILE: axolotl/ecc/ec.py
  class ECPublicKey (line 6) | class ECPublicKey(object):
    method serialize (line 12) | def serialize(self):
    method getType (line 16) | def getType(self):
  class ECPrivateKey (line 20) | class ECPrivateKey(object):
    method serialize (line 24) | def serialize(self):
    method getType (line 28) | def getType(self):

FILE: axolotl/ecc/eckeypair.py
  class ECKeyPair (line 4) | class ECKeyPair():
    method __init__ (line 5) | def __init__(self, publicKey, privateKey):
    method getPrivateKey (line 13) | def getPrivateKey(self):
    method getPublicKey (line 16) | def getPublicKey(self):

FILE: axolotl/groups/groupcipher.py
  class GroupCipher (line 11) | class GroupCipher:
    method __init__ (line 12) | def __init__(self, senderKeyStore, senderKeyName):
    method encrypt (line 20) | def encrypt(self, paddedPlaintext):
    method decrypt (line 42) | def decrypt(self, senderKeyMessageBytes):
    method getSenderKey (line 65) | def getSenderKey(self, senderKeyState, iteration):
    method getPlainText (line 85) | def getPlainText(self, iv, key, ciphertext):
    method getCipherText (line 98) | def getCipherText(self, iv, key, plaintext):

FILE: axolotl/groups/groupsessionbuilder.py
  class GroupSessionBuilder (line 6) | class GroupSessionBuilder:
    method __init__ (line 7) | def __init__(self, senderKeyStore):
    method process (line 10) | def process(self, senderKeyName, senderKeyDistributionMessage):
    method create (line 23) | def create(self, senderKeyName):

FILE: axolotl/groups/ratchet/senderchainkey.py
  class SenderChainKey (line 9) | class SenderChainKey:
    method __init__ (line 13) | def __init__(self, iteration, chainKey):
    method getIteration (line 21) | def getIteration(self):
    method getSenderMessageKey (line 24) | def getSenderMessageKey(self):
    method getNext (line 27) | def getNext(self):
    method getSeed (line 30) | def getSeed(self):
    method getDerivative (line 33) | def getDerivative(self, seed, key):

FILE: axolotl/groups/ratchet/sendermessagekey.py
  class SenderMessageKey (line 7) | class SenderMessageKey:
    method __init__ (line 8) | def __init__(self, iteration, seed):
    method getIteration (line 21) | def getIteration(self):
    method getIv (line 24) | def getIv(self):
    method getCipherKey (line 27) | def getCipherKey(self):
    method getSeed (line 30) | def getSeed(self):

FILE: axolotl/groups/senderkeyname.py
  class SenderKeyName (line 1) | class SenderKeyName(object):
    method __init__ (line 2) | def __init__(self, groupId, senderAxolotlAddress):
    method getGroupId (line 6) | def getGroupId(self):
    method getSender (line 9) | def getSender(self):
    method serialize (line 12) | def serialize(self):
    method __eq__ (line 15) | def __eq__(self, other):
    method __hash__ (line 21) | def __hash__(self):

FILE: axolotl/groups/state/senderkeyrecord.py
  class SenderKeyRecord (line 8) | class SenderKeyRecord:
    method __init__ (line 9) | def __init__(self, serialized=None):
    method isEmpty (line 20) | def isEmpty(self):
    method getSenderKeyState (line 23) | def getSenderKeyState(self, keyId=None):
    method addSenderKeyState (line 35) | def addSenderKeyState(self, id, iteration, chainKey, signatureKey):
    method setSenderKeyState (line 44) | def setSenderKeyState(self, id, iteration, chainKey, signatureKey):
    method serialize (line 54) | def serialize(self):

FILE: axolotl/groups/state/senderkeystate.py
  class SenderKeyState (line 9) | class SenderKeyState:
    method __init__ (line 10) | def __init__(self, id=None, iteration=None, chainKey=None,
    method getKeyId (line 49) | def getKeyId(self):
    method getSenderChainKey (line 52) | def getSenderChainKey(self):
    method setSenderChainKey (line 56) | def setSenderChainKey(self, chainKey):
    method getSigningKeyPublic (line 60) | def getSigningKeyPublic(self):
    method getSigningKeyPrivate (line 63) | def getSigningKeyPrivate(self):
    method hasSenderMessageKey (line 66) | def hasSenderMessageKey(self, iteration):
    method addSenderMessageKey (line 73) | def addSenderMessageKey(self, senderMessageKey):
    method removeSenderMessageKey (line 79) | def removeSenderMessageKey(self, iteration):
    method getStructure (line 95) | def getStructure(self):

FILE: axolotl/groups/state/senderkeystore.py
  class SenderKeyStore (line 6) | class SenderKeyStore(object):
    method storeSenderKey (line 10) | def storeSenderKey(self, senderKeyId, senderKeyRecord):
    method loadSenderKey (line 17) | def loadSenderKey(self, senderKeyId):

FILE: axolotl/identitykey.py
  class IdentityKey (line 6) | class IdentityKey:
    method __init__ (line 7) | def __init__(self, ecPubKeyOrBytes, offset=None):
    method getPublicKey (line 13) | def getPublicKey(self):
    method serialize (line 16) | def serialize(self):
    method get_fingerprint (line 19) | def get_fingerprint(self):
    method __eq__ (line 22) | def __eq__(self, other):
    method hashCode (line 25) | def hashCode(self):

FILE: axolotl/identitykeypair.py
  class IdentityKeyPair (line 8) | class IdentityKeyPair:
    method __init__ (line 9) | def __init__(self, identityKeyPublicKey=None, ecPrivateKey=None, seria...
    method getPublicKey (line 19) | def getPublicKey(self):
    method getPrivateKey (line 22) | def getPrivateKey(self):
    method serialize (line 25) | def serialize(self):

FILE: axolotl/invalidkeyexception.py
  class InvalidKeyException (line 4) | class InvalidKeyException(Exception):

FILE: axolotl/invalidkeyidexception.py
  class InvalidKeyIdException (line 4) | class InvalidKeyIdException(Exception):

FILE: axolotl/invalidmessageexception.py
  class InvalidMessageException (line 4) | class InvalidMessageException(Exception):
    method __init__ (line 5) | def __init__(self, message, exceptions=None):

FILE: axolotl/invalidversionexception.py
  class InvalidVersionException (line 4) | class InvalidVersionException(Exception):

FILE: axolotl/kdf/derivedmessagesecrets.py
  class DerivedMessageSecrets (line 6) | class DerivedMessageSecrets:
    method __init__ (line 12) | def __init__(self, okm):
    method getCipherKey (line 21) | def getCipherKey(self):
    method getMacKey (line 24) | def getMacKey(self):
    method getIv (line 27) | def getIv(self):

FILE: axolotl/kdf/derivedrootsecrets.py
  class DerivedRootSecrets (line 6) | class DerivedRootSecrets:
    method __init__ (line 9) | def __init__(self, okm):
    method getRootKey (line 14) | def getRootKey(self):
    method getChainKey (line 17) | def getChainKey(self):

FILE: axolotl/kdf/hkdf.py
  class HKDF (line 9) | class HKDF(object):
    method createFor (line 14) | def createFor(messageVersion):
    method deriveSecrets (line 25) | def deriveSecrets(self, inputKeyMaterial, info, outputLength, salt=None):
    method extract (line 30) | def extract(self, salt, inputKeyMaterial):
    method expand (line 35) | def expand(self, prk, info, outputSize):
    method getIterationStartOffset (line 58) | def getIterationStartOffset(self):

FILE: axolotl/kdf/hkdfv2.py
  class HKDFv2 (line 6) | class HKDFv2(HKDF):
    method getIterationStartOffset (line 7) | def getIterationStartOffset(self):

FILE: axolotl/kdf/hkdfv3.py
  class HKDFv3 (line 6) | class HKDFv3(HKDF):
    method getIterationStartOffset (line 7) | def getIterationStartOffset(self):

FILE: axolotl/kdf/messagekeys.py
  class MessageKeys (line 4) | class MessageKeys:
    method __init__ (line 5) | def __init__(self, cipherKey, macKey, iv, counter):
    method getCipherKey (line 11) | def getCipherKey(self):
    method getMacKey (line 14) | def getMacKey(self):
    method getIv (line 17) | def getIv(self):
    method getCounter (line 20) | def getCounter(self):

FILE: axolotl/legacymessageexception.py
  class LegacyMessageException (line 4) | class LegacyMessageException(Exception):

FILE: axolotl/nosessionexception.py
  class NoSessionException (line 4) | class NoSessionException(Exception):

FILE: axolotl/protocol/ciphertextmessage.py
  class CiphertextMessage (line 6) | class CiphertextMessage(object):
    method serialize (line 21) | def serialize(self):
    method getType (line 25) | def getType(self):

FILE: axolotl/protocol/keyexchangemessage.py
  class KeyExchangeMessage (line 14) | class KeyExchangeMessage:
    method __init__ (line 19) | def __init__(self, messageVersion=None, sequence=None, flags=None, bas...
    method getVersion (line 80) | def getVersion(self):
    method getBaseKey (line 83) | def getBaseKey(self):
    method getBaseKeySignature (line 86) | def getBaseKeySignature(self):
    method getRatchetKey (line 89) | def getRatchetKey(self):
    method getIdentityKey (line 92) | def getIdentityKey(self):
    method hasIdentityKey (line 95) | def hasIdentityKey(self):
    method getMaxVersion (line 98) | def getMaxVersion(self):
    method isResponse (line 101) | def isResponse(self):
    method isInitiate (line 104) | def isInitiate(self):
    method isResponseForSimultaneousInitiate (line 107) | def isResponseForSimultaneousInitiate(self):
    method getFlags (line 110) | def getFlags(self):
    method getSequence (line 113) | def getSequence(self):
    method serialize (line 116) | def serialize(self):

FILE: axolotl/protocol/prekeywhispermessage.py
  class PreKeyWhisperMessage (line 17) | class PreKeyWhisperMessage(CiphertextMessage):
    method __init__ (line 18) | def __init__(self, messageVersion=None, registrationId=None, preKeyId=...
    method getMessageVersion (line 77) | def getMessageVersion(self):
    method getIdentityKey (line 80) | def getIdentityKey(self):
    method getRegistrationId (line 83) | def getRegistrationId(self):
    method getPreKeyId (line 86) | def getPreKeyId(self):
    method getSignedPreKeyId (line 89) | def getSignedPreKeyId(self):
    method getBaseKey (line 92) | def getBaseKey(self):
    method getWhisperMessage (line 95) | def getWhisperMessage(self):
    method serialize (line 98) | def serialize(self):
    method getType (line 101) | def getType(self):

FILE: axolotl/protocol/senderkeydistributionmessage.py
  class SenderKeyDistributionMessage (line 10) | class SenderKeyDistributionMessage(CiphertextMessage):
    method __init__ (line 11) | def __init__(self, id=None, iteration=None, chainKey=None, signatureKe...
    method serialize (line 68) | def serialize(self):
    method getType (line 71) | def getType(self):
    method getIteration (line 74) | def getIteration(self):
    method getChainKey (line 77) | def getChainKey(self):
    method getSignatureKey (line 80) | def getSignatureKey(self):
    method getId (line 83) | def getId(self):

FILE: axolotl/protocol/senderkeymessage.py
  class SenderKeyMessage (line 12) | class SenderKeyMessage(CiphertextMessage):
    method __init__ (line 15) | def __init__(self, keyId=None, iteration=None, ciphertext=None, signat...
    method getKeyId (line 67) | def getKeyId(self):
    method getIteration (line 70) | def getIteration(self):
    method getCipherText (line 73) | def getCipherText(self):
    method verifySignature (line 76) | def verifySignature(self, signatureKey):
    method getSignature (line 90) | def getSignature(self, signatureKey, serialized):
    method serialize (line 100) | def serialize(self):
    method getType (line 103) | def getType(self):

FILE: axolotl/protocol/whispermessage.py
  class WhisperMessage (line 15) | class WhisperMessage(CiphertextMessage):
    method __init__ (line 18) | def __init__(self, messageVersion=None, macKey=None, ECPublicKey_sende...
    method getSenderRatchetKey (line 68) | def getSenderRatchetKey(self):
    method getMessageVersion (line 71) | def getMessageVersion(self):
    method getCounter (line 74) | def getCounter(self):
    method getBody (line 77) | def getBody(self):
    method verifyMac (line 80) | def verifyMac(self, messageVersion, senderIdentityKey, receiverIdentit...
    method getMac (line 90) | def getMac(self, messageVersion, senderIdentityKey, receiverIdentityKe...
    method serialize (line 100) | def serialize(self):
    method getType (line 103) | def getType(self):
    method isLegacy (line 106) | def isLegacy(self, message):

FILE: axolotl/ratchet/aliceaxolotlparameters.py
  class AliceAxolotlParameters (line 4) | class AliceAxolotlParameters:
    method __init__ (line 5) | def __init__(self, ourIdentityKey, ourBaseKey, theirIdentityKey, their...
    method getOurIdentityKey (line 26) | def getOurIdentityKey(self):
    method getOurBaseKey (line 29) | def getOurBaseKey(self):
    method getTheirIdentityKey (line 32) | def getTheirIdentityKey(self):
    method getTheirSignedPreKey (line 35) | def getTheirSignedPreKey(self):
    method getTheirOneTimePreKey (line 38) | def getTheirOneTimePreKey(self):
    method getTheirRatchetKey (line 41) | def getTheirRatchetKey(self):
    method newBuilder (line 45) | def newBuilder():
    class Builder (line 48) | class Builder:
      method __init__ (line 49) | def __init__(self):
      method setOurIdentityKey (line 57) | def setOurIdentityKey(self, ourIdentityKey):
      method setOurBaseKey (line 61) | def setOurBaseKey(self, ourBaseKey):
      method setTheirRatchetKey (line 65) | def setTheirRatchetKey(self, theirRatchetKey):
      method setTheirIdentityKey (line 69) | def setTheirIdentityKey(self, theirIdentityKey):
      method setTheirSignedPreKey (line 73) | def setTheirSignedPreKey(self, theirSignedPreKey):
      method setTheirOneTimePreKey (line 77) | def setTheirOneTimePreKey(self, theirOneTimePreKey):
      method create (line 81) | def create(self):

FILE: axolotl/ratchet/bobaxolotlparamaters.py
  class BobAxolotlParameters (line 4) | class BobAxolotlParameters:
    method __init__ (line 5) | def __init__(self, ourIdentityKey, ourSignedPreKey, ourRatchetKey, our...
    method getOurIdentityKey (line 26) | def getOurIdentityKey(self):
    method getOurSignedPreKey (line 29) | def getOurSignedPreKey(self):
    method getOurOneTimePreKey (line 32) | def getOurOneTimePreKey(self):
    method getTheirIdentityKey (line 35) | def getTheirIdentityKey(self):
    method getTheirBaseKey (line 38) | def getTheirBaseKey(self):
    method getOurRatchetKey (line 41) | def getOurRatchetKey(self):
    method newBuilder (line 45) | def newBuilder():
    class Builder (line 48) | class Builder:
      method __init__ (line 49) | def __init__(self):
      method setOurIdentityKey (line 57) | def setOurIdentityKey(self, ourIdentityKey):
      method setOurSignedPreKey (line 61) | def setOurSignedPreKey(self, ourSignedPreKey):
      method setOurOneTimePreKey (line 65) | def setOurOneTimePreKey(self, ourOneTimePreKey):
      method setOurRatchetKey (line 69) | def setOurRatchetKey(self, ourRatchetKey):
      method setTheirIdentityKey (line 73) | def setTheirIdentityKey(self, theirIdentityKey):
      method setTheirBaseKey (line 77) | def setTheirBaseKey(self, theirBaseKey):
      method create (line 81) | def create(self):

FILE: axolotl/ratchet/chainkey.py
  class ChainKey (line 10) | class ChainKey:
    method __init__ (line 14) | def __init__(self, kdf, key, index):
    method getKey (line 19) | def getKey(self):
    method getIndex (line 22) | def getIndex(self):
    method getNextChainKey (line 25) | def getNextChainKey(self):
    method getMessageKeys (line 29) | def getMessageKeys(self):
    method getBaseMaterial (line 37) | def getBaseMaterial(self, seedBytes):

FILE: axolotl/ratchet/ratchetingsession.py
  class RatchetingSession (line 13) | class RatchetingSession:
    method initializeSession (line 15) | def initializeSession(sessionState, parameters):
    method initializeSessionAsAlice (line 40) | def initializeSessionAsAlice(sessionState, parameters):
    method initializeSessionAsBob (line 73) | def initializeSessionAsBob(sessionState, parameters):
    method getDiscontinuityBytes (line 103) | def getDiscontinuityBytes():
    method calculateDerivedKeys (line 107) | def calculateDerivedKeys(masterSecret):
    method isAlice (line 115) | def isAlice(ourKey, theirKey):
    class DerivedKeys (line 122) | class DerivedKeys:
      method __init__ (line 123) | def __init__(self, rootKey, chainKey):
      method getRootKey (line 131) | def getRootKey(self):
      method getChainKey (line 134) | def getChainKey(self):

FILE: axolotl/ratchet/rootkey.py
  class RootKey (line 8) | class RootKey:
    method __init__ (line 9) | def __init__(self, kdf, key):
    method getKeyBytes (line 13) | def getKeyBytes(self):
    method createChain (line 16) | def createChain(self, ECPublicKey_theirRatchetKey, ECKeyPair_ourRatche...

FILE: axolotl/ratchet/symmetricaxolotlparameters.py
  class SymmetricAxolotlParameters (line 4) | class SymmetricAxolotlParameters:
    method __init__ (line 5) | def __init__(self, ourBaseKey, ourRatchetKey, ourIdentityKey, theirBas...
    method getOurBaseKey (line 26) | def getOurBaseKey(self):
    method getOurIdentityKey (line 29) | def getOurIdentityKey(self):
    method getTheirRatchetKey (line 32) | def getTheirRatchetKey(self):
    method getTheirIdentityKey (line 35) | def getTheirIdentityKey(self):
    method getTheirBaseKey (line 38) | def getTheirBaseKey(self):
    method getOurRatchetKey (line 41) | def getOurRatchetKey(self):
    method newBuilder (line 45) | def newBuilder():
    class Builder (line 48) | class Builder:
      method __init__ (line 49) | def __init__(self):
      method setOurIdentityKey (line 57) | def setOurIdentityKey(self, ourIdentityKey):
      method setOurBaseKey (line 61) | def setOurBaseKey(self, ourBaseKey):
      method setOurRatchetKey (line 65) | def setOurRatchetKey(self, ourRatchetKey):
      method setTheirRatchetKey (line 69) | def setTheirRatchetKey(self, theirRatchetKey):
      method setTheirIdentityKey (line 73) | def setTheirIdentityKey(self, theirIdentityKey):
      method setTheirBaseKey (line 77) | def setTheirBaseKey(self, theirBaseKey):
      method create (line 81) | def create(self):

FILE: axolotl/sessionbuilder.py
  class SessionBuilder (line 23) | class SessionBuilder:
    method __init__ (line 24) | def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, ident...
    method process (line 32) | def process(self, sessionRecord, message):
    method processV3 (line 50) | def processV3(self, sessionRecord, message):
    method processPreKeyBundle (line 88) | def processPreKeyBundle(self, preKey):
    method processKeyExchangeMessage (line 133) | def processKeyExchangeMessage(self, keyExchangeMessage):
    method processInitiate (line 147) | def processInitiate(self, keyExchangeMessage):
    method processResponse (line 191) | def processResponse(self, keyExchangeMessage):
    method processInitKeyExchangeMessage (line 229) | def processInitKeyExchangeMessage(self):

FILE: axolotl/sessioncipher.py
  class SessionCipher (line 22) | class SessionCipher:
    method __init__ (line 23) | def __init__(self, sessionStore, preKeyStore, signedPreKeyStore, ident...
    method encrypt (line 31) | def encrypt(self, paddedMessage):
    method decryptMsg (line 63) | def decryptMsg(self, ciphertext, textMsg=True):
    method decryptPkmsg (line 80) | def decryptPkmsg(self, ciphertext, textMsg=True):
    method decryptWithSessionRecord (line 96) | def decryptWithSessionRecord(self, sessionRecord, cipherText):
    method decryptWithSessionState (line 125) | def decryptWithSessionState(self, sessionState, ciphertextMessage):
    method getOrCreateChainKey (line 149) | def getOrCreateChainKey(self, sessionState, ECPublickKey_theirEphemeral):
    method getOrCreateMessageKeys (line 166) | def getOrCreateMessageKeys(self, sessionState, ECPublicKey_theirEpheme...
    method getCiphertext (line 186) | def getCiphertext(self, version, messageKeys, plainText):
    method getPlaintext (line 195) | def getPlaintext(self, version, messageKeys, cipherText):
    method getCipher (line 200) | def getCipher(self, key, iv):
  class AESCipher (line 203) | class AESCipher:
    method __init__ (line 204) | def __init__(self, key, iv):
    method encrypt (line 209) | def encrypt(self, raw):
    method decrypt (line 219) | def decrypt(self, enc):

FILE: axolotl/state/axolotlstore.py
  class AxolotlStore (line 11) | class AxolotlStore(IdentityKeyStore, PreKeyStore, SignedPreKeyStore, Ses...

FILE: axolotl/state/identitykeystore.py
  class IdentityKeyStore (line 6) | class IdentityKeyStore(object):
    method getIdentityKeyPair (line 10) | def getIdentityKeyPair(self):
    method getLocalRegistrationId (line 14) | def getLocalRegistrationId(self):
    method saveIdentity (line 18) | def saveIdentity(self, recepientId, identityKey):
    method isTrustedIdentity (line 22) | def isTrustedIdentity(self, recepientId, identityKey):

FILE: axolotl/state/prekeybundle.py
  class PreKeyBundle (line 4) | class PreKeyBundle:
    method __init__ (line 5) | def __init__(self, registrationId, deviceId, preKeyId, ECPublicKey_pre...
    method getDeviceId (line 17) | def getDeviceId(self):
    method getPreKeyId (line 20) | def getPreKeyId(self):
    method getPreKey (line 23) | def getPreKey(self):
    method getSignedPreKeyId (line 26) | def getSignedPreKeyId(self):
    method getSignedPreKey (line 29) | def getSignedPreKey(self):
    method getSignedPreKeySignature (line 32) | def getSignedPreKeySignature(self):
    method getIdentityKey (line 35) | def getIdentityKey(self):
    method getRegistrationId (line 38) | def getRegistrationId(self):

FILE: axolotl/state/prekeyrecord.py
  class PreKeyRecord (line 8) | class PreKeyRecord:
    method __init__ (line 9) | def __init__(self, _id=None, ecKeyPair=None, serialized=None):
    method getId (line 18) | def getId(self):
    method getKeyPair (line 21) | def getKeyPair(self):
    method serialize (line 26) | def serialize(self):

FILE: axolotl/state/prekeystore.py
  class PreKeyStore (line 6) | class PreKeyStore(object):
    method loadPreKey (line 10) | def loadPreKey(self, preKeyId):
    method storePreKey (line 14) | def storePreKey(self, preKeyId, preKeyRecord):
    method containsPreKey (line 18) | def containsPreKey(self, preKeyId):
    method removePreKey (line 22) | def removePreKey(self, preKeyId):

FILE: axolotl/state/sessionrecord.py
  class SessionRecord (line 7) | class SessionRecord:
    method __init__ (line 10) | def __init__(self, sessionState=None, serialized=None):
    method hasSessionState (line 31) | def hasSessionState(self, version, aliceBaseKey):
    method getSessionState (line 41) | def getSessionState(self):
    method getPreviousSessionStates (line 44) | def getPreviousSessionStates(self):
    method isFresh (line 47) | def isFresh(self):
    method archiveCurrentState (line 50) | def archiveCurrentState(self):
    method promoteState (line 53) | def promoteState(self, promotedState):
    method setState (line 59) | def setState(self, sessionState):
    method serialize (line 62) | def serialize(self):

FILE: axolotl/state/sessionstate.py
  class SessionState (line 13) | class SessionState:
    method __init__ (line 14) | def __init__(self, session=None):
    method getStructure (line 23) | def getStructure(self):
    method getAliceBaseKey (line 26) | def getAliceBaseKey(self):
    method setAliceBaseKey (line 29) | def setAliceBaseKey(self, aliceBaseKey):
    method setSessionVersion (line 32) | def setSessionVersion(self, version):
    method getSessionVersion (line 35) | def getSessionVersion(self):
    method setRemoteIdentityKey (line 39) | def setRemoteIdentityKey(self, identityKey):
    method setLocalIdentityKey (line 42) | def setLocalIdentityKey(self, identityKey):
    method getRemoteIdentityKey (line 45) | def getRemoteIdentityKey(self):
    method getLocalIdentityKey (line 50) | def getLocalIdentityKey(self):
    method getPreviousCounter (line 53) | def getPreviousCounter(self):
    method setPreviousCounter (line 56) | def setPreviousCounter(self, previousCounter):
    method getRootKey (line 59) | def getRootKey(self):
    method setRootKey (line 62) | def setRootKey(self, rootKey):
    method getSenderRatchetKey (line 65) | def getSenderRatchetKey(self):
    method getSenderRatchetKeyPair (line 68) | def getSenderRatchetKeyPair(self):
    method hasReceiverChain (line 74) | def hasReceiverChain(self, ECPublickKey_senderEphemeral):
    method hasSenderChain (line 77) | def hasSenderChain(self):
    method getReceiverChain (line 80) | def getReceiverChain(self, ECPublickKey_senderEphemeral):
    method getReceiverChainKey (line 90) | def getReceiverChainKey(self, ECPublicKey_senderEphemeral):
    method addReceiverChain (line 100) | def addReceiverChain(self, ECPublickKey_senderRatchetKey, chainKey):
    method setSenderChain (line 113) | def setSenderChain(self, ECKeyPair_senderRatchetKeyPair, chainKey):
    method getSenderChainKey (line 124) | def getSenderChainKey(self):
    method setSenderChainKey (line 129) | def setSenderChainKey(self, ChainKey_nextChainKey):
    method hasMessageKeys (line 135) | def hasMessageKeys(self, ECPublickKey_senderEphemeral, counter):
    method removeMessageKeys (line 149) | def removeMessageKeys(self, ECPublicKey_senderEphemeral, counter):
    method setMessageKeys (line 170) | def setMessageKeys(self, ECPublicKey_senderEphemeral, messageKeys):
    method setReceiverChainKey (line 184) | def setReceiverChainKey(self, ECPublicKey_senderEphemeral, chainKey):
    method setPendingKeyExchange (line 194) | def setPendingKeyExchange(self, sequence, ourBaseKey, ourRatchetKey, o...
    method getPendingKeyExchangeSequence (line 212) | def getPendingKeyExchangeSequence(self):
    method getPendingKeyExchangeBaseKey (line 215) | def getPendingKeyExchangeBaseKey(self):
    method getPendingKeyExchangeRatchetKey (line 220) | def getPendingKeyExchangeRatchetKey(self):
    method getPendingKeyExchangeIdentityKey (line 225) | def getPendingKeyExchangeIdentityKey(self):
    method hasPendingKeyExchange (line 231) | def hasPendingKeyExchange(self):
    method setUnacknowledgedPreKeyMessage (line 234) | def setUnacknowledgedPreKeyMessage(self, preKeyId, signedPreKeyId, bas...
    method hasUnacknowledgedPreKeyMessage (line 246) | def hasUnacknowledgedPreKeyMessage(self):
    method getUnacknowledgedPreKeyMessageItems (line 249) | def getUnacknowledgedPreKeyMessageItems(self):
    method clearUnacknowledgedPreKeyMessage (line 258) | def clearUnacknowledgedPreKeyMessage(self):
    method setRemoteRegistrationId (line 261) | def setRemoteRegistrationId(self, registrationId):
    method getRemoteRegistrationId (line 264) | def getRemoteRegistrationId(self, registrationId):
    method setLocalRegistrationId (line 267) | def setLocalRegistrationId(self, registrationId):
    method getLocalRegistrationId (line 270) | def getLocalRegistrationId(self):
    method serialize (line 273) | def serialize(self):
    class UnacknowledgedPreKeyMessageItems (line 276) | class UnacknowledgedPreKeyMessageItems:
      method __init__ (line 277) | def __init__(self, preKeyId, signedPreKeyId, baseKey):
      method getPreKeyId (line 287) | def getPreKeyId(self):
      method getSignedPreKeyId (line 290) | def getSignedPreKeyId(self):
      method getBaseKey (line 293) | def getBaseKey(self):

FILE: axolotl/state/sessionstore.py
  class SessionStore (line 6) | class SessionStore(object):
    method loadSession (line 10) | def loadSession(self, recepientId, deviceId):
    method getSubDeviceSessions (line 14) | def getSubDeviceSessions(self, recepientId):
    method storeSession (line 18) | def storeSession(self, recepientId, deviceId, sessionRecord):
    method containsSession (line 22) | def containsSession(self, recepientId, deviceId):
    method deleteSession (line 26) | def deleteSession(self, recepientId, deviceId):
    method deleteAllSessions (line 30) | def deleteAllSessions(self, recepientId):

FILE: axolotl/state/signedprekeyrecord.py
  class SignedPreKeyRecord (line 8) | class SignedPreKeyRecord:
    method __init__ (line 9) | def __init__(self, _id=None, timestamp=None, ecKeyPair=None, signature...
    method getId (line 20) | def getId(self):
    method getTimestamp (line 23) | def getTimestamp(self):
    method getKeyPair (line 26) | def getKeyPair(self):
    method getSignature (line 32) | def getSignature(self):
    method serialize (line 35) | def serialize(self):

FILE: axolotl/state/signedprekeystore.py
  class SignedPreKeyStore (line 6) | class SignedPreKeyStore(object):
    method loadSignedPreKey (line 10) | def loadSignedPreKey(self, signedPreKeyId):
    method loadSignedPreKeys (line 14) | def loadSignedPreKeys(self):
    method storeSignedPreKey (line 18) | def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord):
    method containsSignedPreKey (line 22) | def containsSignedPreKey(self, signedPreKeyId):
    method removeSignedPreKey (line 26) | def removeSignedPreKey(self, signedPreKeyId):

FILE: axolotl/statekeyexchangeexception.py
  class StaleKeyExchangeException (line 4) | class StaleKeyExchangeException(Exception):

FILE: axolotl/tests/groups/inmemorysenderkeystore.py
  class InMemorySenderKeyStore (line 7) | class InMemorySenderKeyStore(SenderKeyStore):
    method __init__ (line 8) | def __init__(self):
    method storeSenderKey (line 11) | def storeSenderKey(self, senderKeyName, senderKeyRecord):
    method loadSenderKey (line 14) | def loadSenderKey(self, senderKeyName):

FILE: axolotl/tests/groups/test_groupcipher.py
  class GroupCipherTest (line 20) | class GroupCipherTest(unittest.TestCase):
    method test_noSession (line 22) | def test_noSession(self):
    method test_basicEncryptDecrypt (line 42) | def test_basicEncryptDecrypt(self):
    method test_basicRatchet (line 62) | def test_basicRatchet(self):
    method test_outOfOrder (line 101) | def test_outOfOrder(self):
    method test_encryptNoSession (line 128) | def test_encryptNoSession(self):

FILE: axolotl/tests/inmemoryaxolotlstore.py
  class InMemoryAxolotlStore (line 10) | class InMemoryAxolotlStore(AxolotlStore):
    method __init__ (line 11) | def __init__(self):
    method getIdentityKeyPair (line 17) | def getIdentityKeyPair(self):
    method getLocalRegistrationId (line 20) | def getLocalRegistrationId(self):
    method saveIdentity (line 23) | def saveIdentity(self, recepientId, identityKey):
    method isTrustedIdentity (line 26) | def isTrustedIdentity(self, recepientId, identityKey):
    method loadPreKey (line 29) | def loadPreKey(self, preKeyId):
    method storePreKey (line 32) | def storePreKey(self, preKeyId, preKeyRecord):
    method containsPreKey (line 35) | def containsPreKey(self, preKeyId):
    method removePreKey (line 38) | def removePreKey(self, preKeyId):
    method loadSession (line 41) | def loadSession(self, recepientId, deviceId):
    method getSubDeviceSessions (line 44) | def getSubDeviceSessions(self, recepientId):
    method storeSession (line 47) | def storeSession(self, recepientId, deviceId, sessionRecord):
    method containsSession (line 50) | def containsSession(self, recepientId, deviceId):
    method deleteSession (line 53) | def deleteSession(self, recepientId, deviceId):
    method deleteAllSessions (line 56) | def deleteAllSessions(self, recepientId):
    method loadSignedPreKey (line 59) | def loadSignedPreKey(self, signedPreKeyId):
    method loadSignedPreKeys (line 62) | def loadSignedPreKeys(self):
    method storeSignedPreKey (line 65) | def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord):
    method containsSignedPreKey (line 68) | def containsSignedPreKey(self, signedPreKeyId):
    method removeSignedPreKey (line 71) | def removeSignedPreKey(self, signedPreKeyId):

FILE: axolotl/tests/inmemoryidentitykeystore.py
  class InMemoryIdentityKeyStore (line 10) | class InMemoryIdentityKeyStore(IdentityKeyStore):
    method __init__ (line 11) | def __init__(self):
    method getIdentityKeyPair (line 18) | def getIdentityKeyPair(self):
    method getLocalRegistrationId (line 21) | def getLocalRegistrationId(self):
    method saveIdentity (line 24) | def saveIdentity(self, recepientId, identityKey):
    method isTrustedIdentity (line 27) | def isTrustedIdentity(self, recepientId, identityKey):

FILE: axolotl/tests/inmemoryprekeystore.py
  class InMemoryPreKeyStore (line 8) | class InMemoryPreKeyStore(PreKeyStore):
    method __init__ (line 9) | def __init__(self):
    method loadPreKey (line 12) | def loadPreKey(self, preKeyId):
    method storePreKey (line 18) | def storePreKey(self, preKeyId, preKeyRecord):
    method containsPreKey (line 21) | def containsPreKey(self, preKeyId):
    method removePreKey (line 24) | def removePreKey(self, preKeyId):

FILE: axolotl/tests/inmemorysessionstore.py
  class InMemorySessionStore (line 7) | class InMemorySessionStore(SessionStore):
    method __init__ (line 8) | def __init__(self):
    method loadSession (line 11) | def loadSession(self, recepientId, deviceId):
    method getSubDeviceSessions (line 17) | def getSubDeviceSessions(self, recepientId):
    method storeSession (line 25) | def storeSession(self, recepientId, deviceId, sessionRecord):
    method containsSession (line 28) | def containsSession(self, recepientId, deviceId):
    method deleteSession (line 31) | def deleteSession(self, recepientId, deviceId):
    method deleteAllSessions (line 34) | def deleteAllSessions(self, recepientId):

FILE: axolotl/tests/inmemorysignedprekeystore.py
  class InMemorySignedPreKeyStore (line 8) | class InMemorySignedPreKeyStore(SignedPreKeyStore):
    method __init__ (line 9) | def __init__(self):
    method loadSignedPreKey (line 12) | def loadSignedPreKey(self, signedPreKeyId):
    method loadSignedPreKeys (line 18) | def loadSignedPreKeys(self):
    method storeSignedPreKey (line 25) | def storeSignedPreKey(self, signedPreKeyId, signedPreKeyRecord):
    method containsSignedPreKey (line 28) | def containsSignedPreKey(self, signedPreKeyId):
    method removeSignedPreKey (line 31) | def removeSignedPreKey(self, signedPreKeyId):

FILE: axolotl/tests/kdf/test_hkdf.py
  class HKDFTest (line 8) | class HKDFTest(unittest.TestCase):
    method test_vectorV3 (line 9) | def test_vectorV3(self):
    method test_vectorLongV3 (line 24) | def test_vectorLongV3(self):
    method test_vectorV3_ (line 56) | def test_vectorV3_(self):

FILE: axolotl/tests/ratchet/test_chainkey.py
  class ChainKeyTest (line 9) | class ChainKeyTest(unittest.TestCase):
    method test_chainKeyDerivationV2 (line 10) | def test_chainKeyDerivationV2(self):

FILE: axolotl/tests/ratchet/test_ratchetingsession.py
  class RatchetingSessionTest (line 14) | class RatchetingSessionTest(unittest.TestCase):
    method test_ratchetingSessionAsBob (line 15) | def test_ratchetingSessionAsBob(self):

FILE: axolotl/tests/ratchet/test_rootkey.py
  class RootKeyTest (line 11) | class RootKeyTest(unittest.TestCase):
    method test_rootKeyDerivationV2 (line 12) | def test_rootKeyDerivationV2(self):

FILE: axolotl/tests/test_sessionbuilder.py
  class SessionBuilderTest (line 23) | class SessionBuilderTest(unittest.TestCase):
    method test_basicPreKeyV2 (line 27) | def test_basicPreKeyV2(self):
    method test_basicPreKeyV3 (line 50) | def test_basicPreKeyV3(self):
    method test_badSignedPreKeySignature (line 168) | def test_badSignedPreKeySignature(self):
    method test_basicKeyExchange (line 199) | def test_basicKeyExchange(self):
    method runInteraction (line 255) | def runInteraction(self, aliceStore, bobStore):

FILE: axolotl/tests/test_sessioncipher.py
  class SessionCipherTest (line 16) | class SessionCipherTest(unittest.TestCase):
    method test_basicSessionV3 (line 18) | def test_basicSessionV3(self):
    method runInteraction (line 24) | def runInteraction(self, aliceSessionRecord, bobSessionRecord):
    method initializeSessionsV3 (line 65) | def initializeSessionsV3(self, aliceSessionState, bobSessionState):

FILE: axolotl/tests/test_sigs.py
  class Curve25519Test (line 9) | class Curve25519Test(unittest.TestCase):
    method test_agreement (line 10) | def test_agreement(self):
    method test_randomAgreements (line 42) | def test_randomAgreements(self):
    method test_gensig (line 51) | def test_gensig(self):
    method test_signature (line 55) | def test_signature(self):

FILE: axolotl/tests/util/test_byteutil.py
  class ByteUtilTest (line 9) | class ByteUtilTest(unittest.TestCase):
    method test_split (line 10) | def test_split(self):

FILE: axolotl/untrustedidentityexception.py
  class UntrustedIdentityException (line 3) | class UntrustedIdentityException(Exception):
    method __init__ (line 4) | def __init__(self, name, identityKey):
    method getName (line 8) | def getName(self):
    method getIdentityKey (line 11) | def getIdentityKey(self):

FILE: axolotl/util/byteutil.py
  class ByteUtil (line 4) | class ByteUtil:
    method combine (line 6) | def combine(*args):
    method split (line 26) | def split(inp, firstLength, secondLength, thirdLength=None):
    method trim (line 36) | def trim(inp, length):
    method intsToByteHighAndLow (line 40) | def intsToByteHighAndLow(highValue, lowValue):
    method highBitsToInt (line 46) | def highBitsToInt(value):
    method lowBitsToInt (line 51) | def lowBitsToInt(value):
    method intToByteArray (line 55) | def intToByteArray(_bytes, offset, value):

FILE: axolotl/util/hexutil.py
  class HexUtil (line 8) | class HexUtil:
    method decodeHex (line 10) | def decodeHex(hexString):

FILE: axolotl/util/keyhelper.py
  class KeyHelper (line 16) | class KeyHelper:
    method __init__ (line 17) | def __init__(self):
    method generateIdentityKeyPair (line 21) | def generateIdentityKeyPair():
    method generateRegistrationId (line 38) | def generateRegistrationId(extended_range=False):
    method getRandomSequence (line 54) | def getRandomSequence(max):
    method generatePreKeys (line 58) | def generatePreKeys(start, count):
    method generateSignedPreKey (line 80) | def generateSignedPreKey(identityKeyPair, signedPreKeyId):
    method generateSenderSigningKey (line 89) | def generateSenderSigningKey():
    method generateSenderKey (line 93) | def generateSenderKey():
    method generateSenderKeyId (line 97) | def generateSenderKeyId():

FILE: axolotl/util/medium.py
  class Medium (line 4) | class Medium:
Condensed preview — 99 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (282K chars).
[
  {
    "path": ".github/FUNDING.yml",
    "chars": 17,
    "preview": "github: [tgalal]\n"
  },
  {
    "path": ".gitignore",
    "chars": 1613,
    "preview": "# Created by https://www.gitignore.io/api/windows,linux,osx,python,vim\n\n### Windows ###\n# Windows image file caches\nThum"
  },
  {
    "path": ".travis.yml",
    "chars": 717,
    "preview": "language: python\npython: '3.7'\n# command to install dependencies\n\nenv:\n  global:\n    - LD_PRELOAD=/lib/x86_64-linux-gnu/"
  },
  {
    "path": "LICENSE",
    "chars": 35122,
    "preview": "GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation,"
  },
  {
    "path": "README.md",
    "chars": 3179,
    "preview": "This is a python port of [libsignal-protocol-java](https://github.com/WhisperSystems/libaxolotl-android) originally writ"
  },
  {
    "path": "axolotl/__init__.py",
    "chars": 158,
    "preview": "# -*- coding: utf-8 -*-\n\n__version__ = '0.2.3'\n__author__ = 'Tarek Galal'\n__email__ = 'tare2.galal@gmail.com'\n__license_"
  },
  {
    "path": "axolotl/axolotladdress.py",
    "chars": 621,
    "preview": "class AxolotlAddress(object):\n    def __init__(self, name, deviceId):\n        self.name = name\n        self.deviceId = d"
  },
  {
    "path": "axolotl/duplicatemessagexception.py",
    "chars": 79,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass DuplicateMessageException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/ecc/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "axolotl/ecc/curve.py",
    "chars": 3024,
    "preview": "# -*- coding: utf-8 -*-\n\nimport os\n\nfrom .eckeypair import ECKeyPair\nfrom ..invalidkeyexception import InvalidKeyExcepti"
  },
  {
    "path": "axolotl/ecc/djbec.py",
    "chars": 1487,
    "preview": "# -*- coding: utf-8 -*-\n\nimport struct\n\nfrom .ec import ECPublicKey, ECPrivateKey\nfrom ..util.byteutil import ByteUtil\n\n"
  },
  {
    "path": "axolotl/ecc/ec.py",
    "chars": 426,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass ECPublicKey(object):\n    __metaclass__ = abc.ABCMeta\n\n    KEY_SIZE = 33\n\n   "
  },
  {
    "path": "axolotl/ecc/eckeypair.py",
    "chars": 384,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass ECKeyPair():\n    def __init__(self, publicKey, privateKey):\n        \"\"\"\n        :type pu"
  },
  {
    "path": "axolotl/groups/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/groups/groupcipher.py",
    "chars": 4374,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..invalidkeyidexception import InvalidKeyIdException\nfrom ..invalidkeyexception import Inv"
  },
  {
    "path": "axolotl/groups/groupsessionbuilder.py",
    "chars": 2177,
    "preview": "# -*- coding: utf-8 -*-\nfrom ..protocol.senderkeydistributionmessage import SenderKeyDistributionMessage\nfrom ..invalidk"
  },
  {
    "path": "axolotl/groups/ratchet/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/groups/ratchet/senderchainkey.py",
    "chars": 952,
    "preview": "# -*- coding: utf-8 -*-\n\nimport hashlib\nimport hmac\n\nfrom .sendermessagekey import SenderMessageKey\n\n\nclass SenderChainK"
  },
  {
    "path": "axolotl/groups/ratchet/sendermessagekey.py",
    "chars": 710,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ...kdf.hkdfv3 import HKDFv3\nfrom ...util.byteutil import ByteUtil\n\n\nclass SenderMessageKey"
  },
  {
    "path": "axolotl/groups/senderkeyname.py",
    "chars": 681,
    "preview": "class SenderKeyName(object):\n    def __init__(self, groupId, senderAxolotlAddress):\n        self.groupId = groupId\n     "
  },
  {
    "path": "axolotl/groups/state/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/groups/state/senderkeyrecord.py",
    "chars": 2084,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ...state.storageprotos_pb2 import SenderKeyRecordStructure\nfrom .senderkeystate import Sen"
  },
  {
    "path": "axolotl/groups/state/senderkeystate.py",
    "chars": 4001,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ...state import storageprotos_pb2 as storageprotos\nfrom ..ratchet.senderchainkey import Se"
  },
  {
    "path": "axolotl/groups/state/senderkeystore.py",
    "chars": 409,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass SenderKeyStore(object):\n    __metaclass__ = abc.ABCMeta\n\n    @abc.abstractme"
  },
  {
    "path": "axolotl/identitykey.py",
    "chars": 636,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .ecc.curve import Curve\n\n\nclass IdentityKey:\n    def __init__(self, ecPubKeyOrBytes, offse"
  },
  {
    "path": "axolotl/identitykeypair.py",
    "chars": 1021,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .state.storageprotos_pb2 import IdentityKeyPairStructure\nfrom .identitykey import Identity"
  },
  {
    "path": "axolotl/invalidkeyexception.py",
    "chars": 73,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass InvalidKeyException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/invalidkeyidexception.py",
    "chars": 75,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass InvalidKeyIdException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/invalidmessageexception.py",
    "chars": 246,
    "preview": "# -*- cofing: utf-8 -*-\n\n\nclass InvalidMessageException(Exception):\n    def __init__(self, message, exceptions=None):\n  "
  },
  {
    "path": "axolotl/invalidversionexception.py",
    "chars": 77,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass InvalidVersionException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/kdf/__init__.py",
    "chars": 46,
    "preview": "# -*- coding: utf-8 -*-\n\n__author__ = 'tarek'\n"
  },
  {
    "path": "axolotl/kdf/derivedmessagesecrets.py",
    "chars": 686,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..util.byteutil import ByteUtil\n\n\nclass DerivedMessageSecrets:\n    SIZE = 80\n    CIPHER_KE"
  },
  {
    "path": "axolotl/kdf/derivedrootsecrets.py",
    "chars": 352,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..util.byteutil import ByteUtil\n\n\nclass DerivedRootSecrets:\n    SIZE = 64\n\n    def __init_"
  },
  {
    "path": "axolotl/kdf/hkdf.py",
    "chars": 1837,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\nimport hmac\nimport hashlib\nimport math\n\n\nclass HKDF(object):\n    __metaclass__ = abc"
  },
  {
    "path": "axolotl/kdf/hkdfv2.py",
    "chars": 126,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .hkdf import HKDF\n\n\nclass HKDFv2(HKDF):\n    def getIterationStartOffset(self):\n        ret"
  },
  {
    "path": "axolotl/kdf/hkdfv3.py",
    "chars": 127,
    "preview": "# -*- codsing: utf-8 -*-\n\nfrom .hkdf import HKDF\n\n\nclass HKDFv3(HKDF):\n    def getIterationStartOffset(self):\n        re"
  },
  {
    "path": "axolotl/kdf/messagekeys.py",
    "chars": 429,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass MessageKeys:\n    def __init__(self, cipherKey, macKey, iv, counter):\n        self.cipher"
  },
  {
    "path": "axolotl/legacymessageexception.py",
    "chars": 76,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass LegacyMessageException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/nosessionexception.py",
    "chars": 72,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass NoSessionException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/protobuf/LocalStorageProtocol.proto",
    "chars": 3176,
    "preview": "package textsecure;\n\noption java_package = \"org.whispersystems.libaxolotl.state\";\noption java_outer_classname = \"Storage"
  },
  {
    "path": "axolotl/protobuf/WhisperTextProtocol.proto",
    "chars": 1137,
    "preview": "package textsecure;\n\noption java_package = \"org.whispersystems.libaxolotl.protocol\";\noption java_outer_classname = \"Whis"
  },
  {
    "path": "axolotl/protocol/__init__.py",
    "chars": 46,
    "preview": "# -*- coding: utf-8 -*-\n\n__author__ = 'tarek'\n"
  },
  {
    "path": "axolotl/protocol/ciphertextmessage.py",
    "chars": 528,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass CiphertextMessage(object):\n    __metaclass__ = abc.ABCMeta\n\n    UNSUPPORTED_"
  },
  {
    "path": "axolotl/protocol/keyexchangemessage.py",
    "chars": 4545,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .ciphertextmessage import CiphertextMessage\nfrom ..util.byteutil import ByteUtil\nfrom . im"
  },
  {
    "path": "axolotl/protocol/prekeywhispermessage.py",
    "chars": 4082,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom google.protobuf.message import DecodeError\n\nfrom .ciphertextmessage import CiphertextMessa"
  },
  {
    "path": "axolotl/protocol/senderkeydistributionmessage.py",
    "chars": 3286,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .ciphertextmessage import CiphertextMessage\nfrom . import whisperprotos_pb2 as whisperprot"
  },
  {
    "path": "axolotl/protocol/senderkeymessage.py",
    "chars": 4089,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .ciphertextmessage import CiphertextMessage\nfrom ..util.byteutil import ByteUtil\nfrom ..le"
  },
  {
    "path": "axolotl/protocol/whispermessage.py",
    "chars": 4837,
    "preview": "# -*- cosing: utf-8 -*-\n\nimport hmac\nimport hashlib\n\nfrom .ciphertextmessage import CiphertextMessage\nfrom ..util.byteut"
  },
  {
    "path": "axolotl/protocol/whisperprotos_pb2.py",
    "chars": 13649,
    "preview": "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n# source: WhisperTextProtocol.proto\n\nimport sys\n_b=sys.versio"
  },
  {
    "path": "axolotl/ratchet/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/ratchet/aliceaxolotlparameters.py",
    "chars": 2826,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass AliceAxolotlParameters:\n    def __init__(self, ourIdentityKey, ourBaseKey, theirIdentity"
  },
  {
    "path": "axolotl/ratchet/bobaxolotlparamaters.py",
    "chars": 2739,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass BobAxolotlParameters:\n    def __init__(self, ourIdentityKey, ourSignedPreKey, ourRatchet"
  },
  {
    "path": "axolotl/ratchet/chainkey.py",
    "chars": 1328,
    "preview": "# -*- coding: utf-8 -*-\n\nimport hmac\nimport hashlib\n\nfrom ..kdf.derivedmessagesecrets import DerivedMessageSecrets\nfrom "
  },
  {
    "path": "axolotl/ratchet/ratchetingsession.py",
    "chars": 6181,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..ecc.curve import Curve\nfrom .bobaxolotlparamaters import BobAxolotlParameters\nfrom .alic"
  },
  {
    "path": "axolotl/ratchet/rootkey.py",
    "chars": 1027,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..ecc.curve import Curve\nfrom ..kdf.derivedrootsecrets import DerivedRootSecrets\nfrom .cha"
  },
  {
    "path": "axolotl/ratchet/symmetricaxolotlparameters.py",
    "chars": 2713,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass SymmetricAxolotlParameters:\n    def __init__(self, ourBaseKey, ourRatchetKey, ourIdentit"
  },
  {
    "path": "axolotl/sessionbuilder.py",
    "chars": 12012,
    "preview": "# -*- coding: utf-8 -*-\n\nimport logging\n\nfrom .ecc.curve import Curve\nfrom .ratchet.aliceaxolotlparameters import AliceA"
  },
  {
    "path": "axolotl/sessioncipher.py",
    "chars": 9938,
    "preview": "# -*- coding: utf-8 -*-\n\nimport sys\n\nfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\nfrom c"
  },
  {
    "path": "axolotl/state/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/state/axolotlstore.py",
    "chars": 327,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\nfrom .identitykeystore import IdentityKeyStore\nfrom .prekeystore import PreKeyStore"
  },
  {
    "path": "axolotl/state/identitykeystore.py",
    "chars": 439,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass IdentityKeyStore(object):\n    __metaclass__ = abc.ABCMeta\n\n    @abc.abstract"
  },
  {
    "path": "axolotl/state/prekeybundle.py",
    "chars": 1150,
    "preview": "# -*- cosing: utf-8 -*-\n\n\nclass PreKeyBundle:\n    def __init__(self, registrationId, deviceId, preKeyId, ECPublicKey_pre"
  },
  {
    "path": "axolotl/state/prekeyrecord.py",
    "chars": 934,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom .storageprotos_pb2 import PreKeyRecordStructure\nfrom ..ecc.curve import Curve\nfrom ..ecc.e"
  },
  {
    "path": "axolotl/state/prekeystore.py",
    "chars": 414,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass PreKeyStore(object):\n    __metaclass__ = abc.ABCMeta\n\n    @abc.abstractmetho"
  },
  {
    "path": "axolotl/state/sessionrecord.py",
    "chars": 2265,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom . import storageprotos_pb2 as storageprotos\nfrom .sessionstate import SessionState\n\n\nclass"
  },
  {
    "path": "axolotl/state/sessionstate.py",
    "chars": 12146,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom . import storageprotos_pb2 as storageprotos\nfrom ..identitykeypair import IdentityKey, Ide"
  },
  {
    "path": "axolotl/state/sessionstore.py",
    "chars": 643,
    "preview": "# -*- cosing: utf-8 -*-\n\nimport abc\n\n\nclass SessionStore(object):\n    __metaclass__ = abc.ABCMeta\n\n    @abc.abstractmeth"
  },
  {
    "path": "axolotl/state/signedprekeyrecord.py",
    "chars": 1221,
    "preview": "# -*- coding; utf-8 -*-\n\nfrom .storageprotos_pb2 import SignedPreKeyRecordStructure\nfrom ..ecc.curve import Curve\nfrom ."
  },
  {
    "path": "axolotl/state/signedprekeystore.py",
    "chars": 545,
    "preview": "# -*- coding: utf-8 -*-\n\nimport abc\n\n\nclass SignedPreKeyStore(object):\n    __metaclass__ = abc.ABCMeta\n\n    @abc.abstrac"
  },
  {
    "path": "axolotl/state/storageprotos_pb2.py",
    "chars": 38558,
    "preview": "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n# source: LocalStorageProtocol.proto\n\nimport sys\n_b=sys.versi"
  },
  {
    "path": "axolotl/statekeyexchangeexception.py",
    "chars": 79,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass StaleKeyExchangeException(Exception):\n    pass\n"
  },
  {
    "path": "axolotl/tests/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/tests/groups/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/tests/groups/inmemorysenderkeystore.py",
    "chars": 558,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ...groups.state.senderkeystore import SenderKeyStore\nfrom ...groups.state.senderkeyrecord "
  },
  {
    "path": "axolotl/tests/groups/test_groupcipher.py",
    "chars": 5769,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom .inmemorysenderkeystore import InMemorySenderKeyStore\nfrom ...groups.grou"
  },
  {
    "path": "axolotl/tests/inmemoryaxolotlstore.py",
    "chars": 2775,
    "preview": "# -*- coding: utf8 -*-\n\nfrom ..state.axolotlstore import AxolotlStore\nfrom .inmemoryidentitykeystore import InMemoryIden"
  },
  {
    "path": "axolotl/tests/inmemoryidentitykeystore.py",
    "chars": 1091,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..state.identitykeystore import IdentityKeyStore\nfrom ..ecc.curve import Curve\nfrom ..iden"
  },
  {
    "path": "axolotl/tests/inmemoryprekeystore.py",
    "chars": 764,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..state.prekeystore import PreKeyStore\nfrom ..state.prekeyrecord import PreKeyRecord\nfrom "
  },
  {
    "path": "axolotl/tests/inmemorysessionstore.py",
    "chars": 1183,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..state.sessionstore import SessionStore\nfrom ..state.sessionrecord import SessionRecord\n\n"
  },
  {
    "path": "axolotl/tests/inmemorysignedprekeystore.py",
    "chars": 1080,
    "preview": "# -*- coding: utf-8 -*-\n\nfrom ..state.signedprekeystore import SignedPreKeyStore\nfrom ..state.signedprekeyrecord import "
  },
  {
    "path": "axolotl/tests/kdf/__init__.py",
    "chars": 46,
    "preview": "# -*- cosing: utf-8 -*-\n\n__author__ = 'tarek'\n"
  },
  {
    "path": "axolotl/tests/kdf/test_hkdf.py",
    "chars": 4725,
    "preview": "# -*- coding ;utf-8 -*-\n\nimport unittest\n\nfrom ...kdf.hkdf import HKDF\n\n\nclass HKDFTest(unittest.TestCase):\n    def test"
  },
  {
    "path": "axolotl/tests/ratchet/__init__.py",
    "chars": 46,
    "preview": "# -*- coding: utf-8 -*-\n\n__author__ = 'tarek'\n"
  },
  {
    "path": "axolotl/tests/ratchet/test_chainkey.py",
    "chars": 1933,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ...ratchet.chainkey import ChainKey\nfrom ...kdf.hkdf import HKDF\n\n\nclass "
  },
  {
    "path": "axolotl/tests/ratchet/test_ratchetingsession.py",
    "chars": 5200,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ...identitykey import IdentityKey\nfrom ...identitykeypair import Identity"
  },
  {
    "path": "axolotl/tests/ratchet/test_rootkey.py",
    "chars": 2668,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ...ecc.curve import Curve\nfrom ...ecc.eckeypair import ECKeyPair\nfrom ..."
  },
  {
    "path": "axolotl/tests/test_sessionbuilder.py",
    "chars": 17070,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\nimport time\nimport sys\n\nfrom ..invalidkeyexception import InvalidKeyException\nf"
  },
  {
    "path": "axolotl/tests/test_sessioncipher.py",
    "chars": 4485,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ..state.sessionrecord import SessionRecord\nfrom ..ecc.curve import Curve\n"
  },
  {
    "path": "axolotl/tests/test_sigs.py",
    "chars": 4581,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ..ecc.curve import Curve\nfrom ..util.keyhelper import KeyHelper\n\n\nclass C"
  },
  {
    "path": "axolotl/tests/util/__init__.py",
    "chars": 46,
    "preview": "# -*- coding: utf-8 -*-\n\n__author__ = 'tarek'\n"
  },
  {
    "path": "axolotl/tests/util/test_byteutil.py",
    "chars": 828,
    "preview": "# -*- coding: utf-8 -*-\n\nimport unittest\n\nfrom ...util.byteutil import ByteUtil\n# from ...util.hexutil import HexUtil\n\n\n"
  },
  {
    "path": "axolotl/untrustedidentityexception.py",
    "chars": 289,
    "preview": "# -*- coding: utf-8 -*-\n\nclass UntrustedIdentityException(Exception):\n    def __init__(self, name, identityKey):\n       "
  },
  {
    "path": "axolotl/util/__init__.py",
    "chars": 24,
    "preview": "# -*- coding: utf-8 -*-\n"
  },
  {
    "path": "axolotl/util/byteutil.py",
    "chars": 1819,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass ByteUtil:\n    @staticmethod\n    def combine(*args):\n        baos = bytearray()\n        f"
  },
  {
    "path": "axolotl/util/hexutil.py",
    "chars": 213,
    "preview": "# -*- coding: utf-8 -*-\n\nimport codecs\n\ndecode_hex = codecs.getdecoder(\"hex_codec\")\n\n\nclass HexUtil:\n    @staticmethod\n "
  },
  {
    "path": "axolotl/util/keyhelper.py",
    "chars": 3388,
    "preview": "# -*- coding: utf-8 -*-\n\nimport time\nimport binascii\nimport os\nfrom random import SystemRandom\n\nfrom ..ecc.curve import "
  },
  {
    "path": "axolotl/util/medium.py",
    "chars": 65,
    "preview": "# -*- coding: utf-8 -*-\n\n\nclass Medium:\n    MAX_VALUE = 0xFFFFFF\n"
  },
  {
    "path": "setup.py",
    "chars": 1371,
    "preview": "# -*- coding: utf-8 -*-\n\nimport sys\n\nimport axolotl\nfrom setuptools import find_packages, setup\n\ndeps = ['cryptography',"
  },
  {
    "path": "tox.ini",
    "chars": 464,
    "preview": "# Tox (http://tox.testrun.org/) is a tool for running tests\n# in multiple virtualenvs. This configuration file will run "
  }
]

About this extraction

This page contains the full source code of the tgalal/python-axolotl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 99 files (261.3 KB), approximately 67.9k tokens, and a symbol index with 511 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!