Compare commits

...

365 Commits

Author SHA1 Message Date
Moxie Marlinspike
b914d5ca25 Bump version to 2.3.3
// FREEBIE
2014-12-04 17:35:03 -08:00
Moxie Marlinspike
7411a49572 Updated language translations.
// FREEBIE
2014-12-04 16:44:31 -08:00
Mladen Pejaković
3fcd2bb88d Add Croatian language to list
// FREEBIE

Closes #2167
Fixes #2026
2014-12-04 16:02:42 -08:00
Moxie Marlinspike
978f769d6d Notify on incoming messages when locked.
// FREEBIE

Fixes #2149
2014-12-04 15:49:09 -08:00
Moxie Marlinspike
9d693eef30 Fix for fallback behavior.
// FREEBIE
2014-12-03 14:16:34 -08:00
Moxie Marlinspike
8f79ba1dd1 Merge pull request #2178 from mcginty/async-media-preview
media preview fixes
2014-12-03 09:09:43 -08:00
Jake McGinty
15613894f0 load image previews asynchronously
// FREEBIE
2014-12-03 13:03:03 +00:00
Jake McGinty
a88fbba49f use Loader when conversation is updated instead of requery
// FREEBIE
2014-12-03 04:47:38 +00:00
Jake McGinty
f3f173f653 support mms basic auth
// FREEBIE
2014-12-02 08:59:43 +00:00
Moxie Marlinspike
5002a749cf Merge pull request #2166 from agrajaghh/building.md_ndk_path
Building.md: library -> libaxolotl
2014-12-01 09:06:32 -08:00
agrajaghh
4a107483c1 path changed: library -> libaxolotl 2014-12-01 16:09:55 +01:00
Tal Hacohen
9ef1ea283b Fix notification display order.
Messages in notifications were showing in reverse order,
that is newest on top instead of newest at the bottom making
multiple messages hard to read.

Closes #1984
2014-11-30 08:35:51 -08:00
christian mock
32153ec379 Use "sms_body" extra from Intent
Closes #2071
2014-11-29 19:31:25 -08:00
Mladen Pejaković
ceb82a05ca Add Serbian language to the list
Closes #2008
2014-11-29 13:43:51 -08:00
McLoo
899bf8160d Cleanup of unused strings in strings.xml
//FREEBIE

Closes #2139
2014-11-29 13:35:36 -08:00
McLoo
49f77c9c06 Added l10n for message trimmer
//FREEBIE

Closes #2079
Closes #1868
2014-11-29 13:31:44 -08:00
McLoo
cd5feccdbf Fix selection for hungarian
// FREEBIE

Closes #2025
2014-11-29 13:19:49 -08:00
Moxie Marlinspike
a1da22cee9 Use constant.
// FREEBIE

Closes #1988
2014-11-29 13:12:53 -08:00
Jakob
a950db74c0 add dependencies to BUILDING.md
// FREEBIE

Closes #1809
2014-11-29 11:54:30 -08:00
Jake McGinty
b0891fa986 move log submission to new library
// FREEBIE

Closes #1655
2014-11-29 11:42:25 -08:00
Moxie Marlinspike
b57763f397 Display 'me' for device's local number in group membership list.
// FREEBIE

Fixes #1494
Closes #1505
2014-11-28 10:46:50 -08:00
Moxie Marlinspike
de75a98093 Move JobManager to external project and dependency.
// FREEBIE
2014-11-28 10:10:47 -08:00
Moxie Marlinspike
0d01feebc3 Move directory refresh from a service over to a job.
// FREEBIE
2014-11-27 15:24:26 -08:00
Moxie Marlinspike
0fb7f3b970 Minor cleanup.
// FREEBIE
2014-11-26 10:05:30 -08:00
agrajaghh
a9637baddf PushNetworkException for network errors on external downloads.
Closes #2112
Fixes #1264

// FREEBIE
2014-11-25 09:07:49 -08:00
Moxie Marlinspike
5e61161767 Bump version to 2.3.2
// FREEBIE
2014-11-24 23:44:50 -08:00
Jake McGinty
83d281de71 compat actionbar bg for dark theme
// FREEBIE
2014-11-25 09:28:22 +02:00
Jake McGinty
28f63cf335 Revert "Try to fix LGE menu button NPEs"
This reverts commit f3a3aaca60.
2014-11-25 09:23:57 +02:00
Jake McGinty
f3a3aaca60 Try to fix LGE menu button NPEs
fix based on https://code.google.com/p/android/issues/detail?id=78154

// FREEBIE
2014-11-25 09:17:27 +02:00
agrajaghh
908e8b8746 fix for ringtone selection with android-support-v4-preferencefragment 2014-11-25 09:08:30 +02:00
Jake McGinty
4573f3cb77 reorder window feature requests in MediaPreviewActivity
ActionBar is initialized in a different way by AppCompat v20 compared to
ABS or v21 even...
// FREEBIE
2014-11-25 08:55:40 +02:00
Moxie Marlinspike
d72a3ec669 Do thread trimming as JobManager job rather than AsyncTask.
// FREEBIE
2014-11-24 22:50:32 -08:00
Moxie Marlinspike
3439657bba Guard against fragment disappearing before callback.
// FREEBIE
2014-11-24 22:48:50 -08:00
Moxie Marlinspike
1ad7912e75 Add callback method parameter to axolotl decrypt functions.
// FREEBIE
2014-11-24 12:17:15 -08:00
Moxie Marlinspike
30aff82341 The future is the other direction.
// FREEBIE
2014-11-24 11:37:28 -08:00
Moxie Marlinspike
c54a5b613b Bump version to 2.3.1
// FREEBIE
2014-11-24 11:15:29 -08:00
Moxie Marlinspike
31ad30b3a5 Updated translations.
// FREEBIE
2014-11-24 10:59:03 -08:00
Moxie Marlinspike
4ccb7ebab6 Don't completely disable GCM.
// FREEBIE
2014-11-24 10:48:33 -08:00
Jake McGinty
bf69a90b69 rollback to appcompat v20
v21 appears to just not be ready for production given the bugs.
// FREEBIE
2014-11-24 19:09:33 +02:00
Moxie Marlinspike
bf19307916 Make GCM re-registration failure notification based.
// FREEBIE
2014-11-23 17:12:35 -08:00
Moxie Marlinspike
d42c4229fd Update to latest zxing QR code scanner.
Closes #2078

// FREEBIE
2014-11-22 09:47:02 -08:00
Moxie Marlinspike
31eddbf346 Bump version to 2.3.0
// FREEBIE
2014-11-21 14:49:14 -08:00
Moxie Marlinspike
e9b383d277 Add jobs for pending push messages during migration.
// FREEBIE
2014-11-21 12:53:40 -08:00
Moxie Marlinspike
eeafb81c90 Fix escaping in danish translation.
// FREEBIE
2014-11-21 12:53:24 -08:00
Moxie Marlinspike
02e27c94f2 Update language translations.
// FREEBIE
2014-11-21 11:49:35 -08:00
Jake McGinty
167386ea49 make the light theme light
Fixes #2111
Tested on GB and LP
// FREEBIE
2014-11-20 21:59:15 -08:00
Jake McGinty
e31994ac77 proguard has guarded its last pro
// FREEBIE
2014-11-20 17:45:31 -08:00
Moxie Marlinspike
ea9a5decac Update gradle-witness and actually use spongycastle.
// FREEBIE
2014-11-20 16:46:35 -08:00
Moxie Marlinspike
1cb191a6ee Move targetSdkVersion back down to 19.
// FREEBIE
2014-11-20 15:58:32 -08:00
Jake McGinty
60737bdd7b proguard: don't warn for test classes
// FREEBIE
2014-11-19 14:52:02 -08:00
Moxie Marlinspike
2dded4888e No more push encoding pretense.
// FREEBIE
2014-11-19 14:45:12 -08:00
Jake McGinty
eaf89735b8 encapsulated delivery icon to separate from lock
and as a bonus some tweaked text sizes and colors
// FREEBIE
2014-11-19 12:56:44 -08:00
Jake McGinty
8fa2f92a91 use latest appcompat and build tools, add dagger pin
// FREEBIE
2014-11-18 17:03:10 -08:00
Moxie Marlinspike
174324e2a0 Potential fix for BroadcastReceiver crash.
// FREEBIE
2014-11-18 14:55:16 -08:00
Jake McGinty
bc3686058a optimize new assets
Thanks to @pejakm for pointing out the emoji optimization.
// FREEBIE
2014-11-18 11:27:10 -08:00
Jake McGinty
0110015c8b remove unused image resources
// FREEBIE
2014-11-18 11:27:10 -08:00
Jake McGinty
5ca8a6d421 materialize conversation item indicators
// FREEBIE
2014-11-18 11:27:08 -08:00
Jake McGinty
0fc9ff7490 add "elevation" window overlay for android 4.x too
// FREEBIE
2014-11-17 12:14:09 -08:00
Jake McGinty
08d939b010 fix AppCompat theme crash
Fixes #2084
// FREEBIE
2014-11-17 11:51:49 -08:00
Jake McGinty
020920d988 silly actionbar shadow issue
// FREEBIE
2014-11-17 11:28:57 -08:00
Moxie Marlinspike
bd3d9ac533 Update JobManager README.md
// FREEBIE
2014-11-17 09:17:14 -08:00
agrajaghh
85670d95ee Fix README.md formatting
// FREEBIE

Closes #2101
2014-11-17 08:57:21 -08:00
Moxie Marlinspike
3d1007d101 Added README
// FREEBIE
2014-11-16 17:24:05 -08:00
Moxie Marlinspike
35821d444e Move responsibility for Context injection out of JavaSerializer.
// FREEBIE
2014-11-16 17:23:33 -08:00
Moxie Marlinspike
3cd7c2d8e5 libjobqueue javadoc and scoping.
// FREEBIE
2014-11-16 15:53:51 -08:00
Moxie Marlinspike
5b08791086 Fix regression with providers being registered.
// FREEBIE
2014-11-14 15:44:49 -08:00
Jake McGinty
31b9dcb5eb stop crashes when sending sms
// FREEBIE
2014-11-15 02:14:37 +03:00
Jake McGinty
43adc75428 add icon back
// FREEBIE
2014-11-15 02:04:17 +03:00
Jake McGinty
67a4523ca7 update gradle+plugins, update gradle-witness
// FREEBIE
2014-11-14 13:07:04 +03:00
Moxie Marlinspike
b35b9be0c8 Add missing copyright headers from libtextsecure.
// FREEBIE
2014-11-12 18:37:16 -08:00
Moxie Marlinspike
9215322846 Abstract out TrustStore interface.
// FREEBIE
2014-11-12 17:09:59 -08:00
Moxie Marlinspike
cbebc040cc Make ProGuard with with Dagger 2014-11-12 16:03:58 -08:00
Moxie Marlinspike
bea26e83da Correctly process push messages with identity key conflicts. 2014-11-12 15:42:43 -08:00
Moxie Marlinspike
a85dbce041 Correctly handle PKWM via SMS. 2014-11-12 15:42:43 -08:00
Moxie Marlinspike
baaa3514d4 Fix delivery receipts in group messages.
Fixes #2056
Fixes #2067
Fixes #2087
2014-11-12 15:42:43 -08:00
Moxie Marlinspike
71fdaac1b2 Fix regressions for registration. 2014-11-12 15:42:43 -08:00
Moxie Marlinspike
fb31319e52 Put everything under either internal or api. 2014-11-12 15:42:43 -08:00
Moxie Marlinspike
08ed90c5ec Split out Util functions. 2014-11-12 15:42:43 -08:00
Moxie Marlinspike
0d102f76cc Move ListenableFutureTask up to parent. 2014-11-12 15:38:23 -08:00
Moxie Marlinspike
28cb1ed85b Move DirectoryUtil up to parent. 2014-11-12 15:29:59 -08:00
Moxie Marlinspike
cd9b20dc9d Move dependency up to parent. 2014-11-12 15:29:59 -08:00
Moxie Marlinspike
f09abff407 Refactor out old classes. 2014-11-12 15:29:59 -08:00
Moxie Marlinspike
f9934bd8e5 Modernize libtextsecure layout 2014-11-12 15:29:59 -08:00
Moxie Marlinspike
1182052c7f Rename library to libtextsecure 2014-11-12 15:29:58 -08:00
Moxie Marlinspike
0d06d50a65 Let's have JobManager only deal with checked exceptions.
Also, switch to Builder for JobManager construction.
2014-11-12 15:29:58 -08:00
Moxie Marlinspike
d9d4ec9d9d Fix some bugs with PKWM padding and attachment detection. 2014-11-12 15:29:58 -08:00
Moxie Marlinspike
9a6f65988f Add support for dependency injection, and accompanying tests. 2014-11-12 15:29:58 -08:00
Moxie Marlinspike
601e233d47 Add account management interface to libtextsecure api 2014-11-12 15:28:08 -08:00
Moxie Marlinspike
ae178fc4ec Move API around a little, eliminate TransportDetails interface. 2014-11-12 15:26:25 -08:00
Moxie Marlinspike
cafe03a70a Transition the outbound pipeline to JobManager jobs. 2014-11-12 15:26:25 -08:00
Moxie Marlinspike
99f42e2ee1 Move API around. 2014-11-12 15:21:32 -08:00
Moxie Marlinspike
a3f1d9cdfd Beginning of libtextsecure refactor.
1) Break out appropriate components.

2) Switch the incoming pipeline from SendReceiveService to
   the JobManager.
2014-11-12 15:21:32 -08:00
Jake McGinty
4cab657ebe clear pending slides when attachment reselected
Fixes #2012

// FREEBIE
2014-10-29 18:50:11 -07:00
Jake McGinty
db6f8618e6 padding workaround for bug in appcompat-v7 21.0.0
bug: https://code.google.com/p/android/issues/detail?id=77982

// FREEBIE
2014-10-29 18:28:20 -07:00
Jake McGinty
98af1fb6ee shorten blocks of text
// FREEBIE
2014-10-29 16:53:25 -07:00
Jake McGinty
ad1d55f12d enable proguard
// FREEBIE
2014-10-29 16:53:21 -07:00
Jake McGinty
7df49811b7 replace ABS with AppCompat
// FREEBIE
2014-10-29 16:51:55 -07:00
Jake McGinty
ff2ac8a66e refactor ListenableFutureTask and make saves async
// FREEBIE
2014-10-28 02:25:41 -05:00
Jake McGinty
53da1f849a in-app image media preview
// FREEBIE
2014-10-28 00:50:01 -05:00
Moxie Marlinspike
503d1ef452 Bump version to 2.2.0
// FREEBIE
2014-10-24 16:51:15 -07:00
Moxie Marlinspike
9accd92757 Updated language translations.
// FREEBIE
2014-10-24 13:18:52 -07:00
agrajaghh
306da92031 Test case and fix for deferred jobs.
Closes #2033
2014-10-24 12:08:03 -07:00
Moxie Marlinspike
e7b6a852c5 Fix bug caused by 1mod8 compatibility issue.
In the switch from v3, we bind identities in the message MAC
instead of doing the 1mod8 trick.  Since identity keys were
never set as 1mod8, it seemed like we could just remove it.

However, PreKeys are durable.  If an old client upgrades to v3,
it has a bunch of keys that *were* set to 1mod8 floating around.
The Curve25519 donna code re-sets the private key bits on every
operation, which results in a different key, and breaks the output
of an agreement.

So now we don't intentionally generate keys with 1mod8, but we
have to remove the donna code to honor existing 1mod8 keys for
the rest of time.  Trevor is squarely to blame.

// FREEBIE
2014-10-23 17:11:46 -07:00
Moxie Marlinspike
9dfaf19516 Merge pull request #2028 from mcginty/revert-generic-contenttype
revert content-type generics
2014-10-22 19:37:45 -07:00
Jake McGinty
34aece0b43 revert content-type generics
// FREEBIE
2014-10-22 19:37:04 -07:00
Moxie Marlinspike
9768de2d5e Short circuit self-send.
// FREEBIE
2014-10-22 18:28:03 -07:00
Moxie Marlinspike
c3eb0ea9db Check job requirements are satisfied in between retry iterations.
// FREEBIE
2014-10-21 13:50:38 -07:00
Moxie Marlinspike
4cdc0a3e61 Make signed prekey generation happen through the job queue. 2014-10-21 12:47:08 -07:00
Moxie Marlinspike
b568ce70b2 Make delivery receipts work correctly for groups. 2014-10-20 21:06:34 -07:00
Moxie Marlinspike
18b0601990 Dependency updates and gradle housekeeping. 2014-10-20 21:06:09 -07:00
Moxie Marlinspike
b308996885 Switch to using our own JobManager.
// FREEBIE
2014-10-20 19:13:06 -07:00
Moxie Marlinspike
73d896f378 Index shouldn't be unique. 2014-10-20 19:02:42 -07:00
Moxie Marlinspike
36ec1d84a1 Implement delivery receipts.
1) Support a "receipt" push message type.

2) Identify messages by timestamp.

3) Introduce a JobManager to handle the queue for network
   dependent jobs.
2014-10-20 19:02:42 -07:00
Moxie Marlinspike
8d6b9ae43e Incorporate PR feedback. Add license and eliminate duplicate code.
// FREEBIE
2014-10-20 18:38:52 -07:00
Moxie Marlinspike
a95cc0eba2 Switch to byte array.
// FREEBIE
2014-10-20 18:35:45 -07:00
Moxie Marlinspike
58d101ff2e Support for job "group ids."
A job can specify a group id, and jobs with the same group id
will run sequentially.
2014-10-20 18:35:45 -07:00
Moxie Marlinspike
544f06451f Persistent job queue, derivative of android-priority-jobqueue.
// FREEBIE
2014-10-20 18:35:45 -07:00
Moxie Marlinspike
20cf775b1e Fix up routing activity actions. 2014-10-20 14:55:34 -07:00
Moxie Marlinspike
5fcc135f81 Make sure senderkeys encrypt is correctly initialized. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
9a0ed659f7 Initial support for sender keys. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
54612159be Update ed25519 extract and tests 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
355d0be78a Introduce new simultaneous initiate strategy.
1) Fix bugs that prevented decrypt() from being non-transactional
   in some cases.

2) Introduce a new unified storage interface.

3) Transition simultaneous initiate from the "needs refresh"
   strategy to one that uses session state resurrection and
   promotion.
2014-10-20 12:25:40 -07:00
Moxie Marlinspike
73b75a4a27 Fix build. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
c4209a65e3 Don't assert on bad padding. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
9dce376780 Correctly handle formatting when "one time PreKey" is absent. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
07c61394e9 When processing PreKeyBundle, archive current session if it exists. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
3e287f930d Better thread safety for session building <-> use. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
7b1a37bd91 Make registration ID optionally extended. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
2db44a1578 Make generated PreKeyIds exclude both 0 and Medium.MAX_VALUE. 2014-10-20 12:25:40 -07:00
Moxie Marlinspike
006c9aae7b Only remove unsigned prekey if bundled message decrypts properly. 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
b147a90463 This exception is never thrown. 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
741171c49f Switch to CBC mode with a derived IV.
1) Since we're not CPU or space constrained (and are in fact
   padding), and since keystream reuse would be more catastrophic
   than IV reuse without chosen plaintext.
2014-10-20 12:25:39 -07:00
Moxie Marlinspike
c375ed8638 MIPS NDK support. Apparently there are mips devices... 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
238f29c90a Updated to latest of Trevor's ref10-extract 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
084f27a2e8 omg trevor 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
27b5bf54cc Remove 1 mod 8. 2014-10-20 12:25:39 -07:00
Moxie Marlinspike
eda393b11c Minor refactoring and renaming. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
c330eef7b9 Make PreKeyWhisperMessage decrypt more reliably atomic. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
1eb3884b7a Update to latest ref10-extract ed25519 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
5ea3b3038e Remove verification tag.
1) Remove verification tag from PreKeyWhisperMessage.

2) Include sender and recipient identity keys in the MAC of
   each WhisperMessage.
2014-10-20 12:25:38 -07:00
Moxie Marlinspike
641ac9aed9 Rename axolotl terminology.
1) ephemeralKey -> ratchetKey

2) Have the caller specify Alice/Bob orientation.

3) Reorganize verification tag.

4) Remove verification tag from key exchange messages, replace
   with signatures in both directions.
2014-10-20 12:25:38 -07:00
Moxie Marlinspike
82bd75fb75 Fix padding problem. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
c94a7b1eff Make sure "previous counter" is never negative. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
4caebdcd06 Update tests for new API. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
b3cece27d6 Update SessionCipher javadocs. 2014-10-20 12:25:38 -07:00
Moxie Marlinspike
819982af7b Rearrange decrypt API.
1) Change SessionBuilder to only establish sessions via
   KeyExchangeMessage and PreKeyBundles.

2) Change SessionCipher to decrypt either WhisperMessage
   or PreKeyWhisperMessage items, automatically building
   a session for the latter.

3) Change SessionCipher to tear down new sessions built
   with PreKeyWhisperMessages if the embedded WhsiperMessage
   fails to decrypt.
2014-10-20 12:25:38 -07:00
Moxie Marlinspike
42cf53e487 Rename "pendingPreKey" to "unacknowledgedPreKeyMessage" 2014-10-20 12:23:15 -07:00
Moxie Marlinspike
e0d2398ca5 Rename InitializationParameters -> AxolotlParameters 2014-10-20 12:23:14 -07:00
Moxie Marlinspike
3f299936bf Only create signed prekey if push registered. 2014-10-20 12:23:14 -07:00
Moxie Marlinspike
540592d71f Upgrade libaxolotl to the latest gradle plugin. 2014-10-20 12:23:14 -07:00
Moxie Marlinspike
5a9e5672d3 Updated README 2014-10-20 12:23:11 -07:00
Moxie Marlinspike
0a23b5fcd5 Added helper method for generating signed PreKeys. 2014-10-20 12:23:10 -07:00
Moxie Marlinspike
f0c22d593f Simplify/clarify internal interfaces and introduce optional types. 2014-10-20 12:23:10 -07:00
Moxie Marlinspike
5f5ddd7c26 Generate SignedPreKey records, improve SignedPreKey cleanup. 2014-10-20 12:23:08 -07:00
Moxie Marlinspike
144f269059 Upgrade curve25519-donna to latest. 2014-10-20 12:17:24 -07:00
Moxie Marlinspike
0d532afd8e Rename 'device key' to 'signed prekey'. 2014-10-20 12:17:24 -07:00
Moxie Marlinspike
07fd17ccda Add padding for push messages.
1) Use 'bit padding.'

1) By default, pad at 160 byte increments.
2014-10-20 12:17:23 -07:00
Moxie Marlinspike
fcaa3f0d73 Simplify HKDF interface. 2014-10-20 12:17:23 -07:00
Moxie Marlinspike
64b40df15b Add V3 support for KeyExchangeMessage case.
1) V3 KeyExchangeMessages can now contain signatures and
   verification tags.
2014-10-20 12:17:23 -07:00
Moxie Marlinspike
77ff9cece8 Add a 'verification tag' to incoming PreKeyWhisperMessage bundles. 2014-10-20 12:17:23 -07:00
Moxie Marlinspike
6326ef73f3 Split HKDF secret derivation and parsing. 2014-10-20 12:17:23 -07:00
Moxie Marlinspike
f29d1e6269 Add support for a compliant HKDF implementation. 2014-10-20 12:17:23 -07:00
Moxie Marlinspike
d6c5e92c9d Collapse RatchetingSessionV2 and RatchetingSessionV3. 2014-10-20 12:17:23 -07:00
Moxie Marlinspike
811479d168 Add first cut of protocol v3 support.
1) Use the new /v2/keys API for storing/retrieving prekey bundles.

2) For sessions built with PreKeyBundle and PreKeyWhisperMessage,
   use a v3 ratcheting session when available.
2014-10-20 12:17:23 -07:00
Moxie Marlinspike
2ed8d333d9 Add ed25519 2014-10-20 12:14:18 -07:00
Moxie Marlinspike
79020cd33c Better FS Locking. 2014-10-20 12:14:18 -07:00
Moxie Marlinspike
c8757c2134 Make helper static. 2014-10-20 12:14:18 -07:00
Moxie Marlinspike
2a65257182 Add serialization helpers for IdentityKeyPair. 2014-10-20 12:14:18 -07:00
Moxie Marlinspike
931605a1c4 Move identity key verification into libaxolotol. With tests. 2014-10-20 12:14:18 -07:00
Moxie Marlinspike
81ae9af2e4 Add "last resort" PreKey generation to KeyHelper. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
e84a0948e9 Update README 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
5239b3e8f8 Add basic README. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
a601c56af1 Collapse SessionRecord, SessionState, and PreKeyRecord interfaces. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
5a3c19fe3e Javadocs, and some minor refactoring. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
af45e5d544 SessionBuilder improvements, more extensive SessionBuilder tests. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
72af8b11c2 Move session construction and KeyExchangeMessage into libaxolotl.
1) Add plain two-way key exchange support libaxolotl by moving
   all the KeyExchangeMessage code there.

2) Move the bulk of KeyExchangeProcessor code to libaxolotl
   for setting up sessions based on retrieved prekeys, received
   prekeybundles, or exchanged key exchange messages.
2014-10-20 12:14:17 -07:00
Moxie Marlinspike
a1db221caf Collapse KeyExchangeMessage and KeyExchangeProcessor interfaces. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
14b8f97de2 Reorganize session store load/store operations. 2014-10-20 12:14:17 -07:00
Moxie Marlinspike
d902c12941 Break core ratchet out into libaxolotol.
1) Break the core cryptography functions out into libaxolotol.

2) The objective for this code is a Java library that isn't
   dependent on any Android functions.  However, while the
   code has been separated from any Android functionality,
   it is still an 'android library project' because of the
   JNI.
2014-10-20 12:10:02 -07:00
Moxie Marlinspike
fe3d91c40c Bump version to 2.1.10
// FREEBIE
2014-10-18 14:19:45 -07:00
Jake McGinty
31167d11dd use wildcard media types, don't crash on preview fail
// FREEBIE
2014-10-17 17:59:56 -07:00
Jake McGinty
6e3751a0c5 sane fallback for media selection on exception
Fixes #1763
// FREEBIE
2014-10-17 17:41:42 -07:00
Jake McGinty
b5941fb3fd actually fallback when mms local params unset
// FREEBIE
2014-10-15 17:14:12 -07:00
Moxie Marlinspike
cfccd367ad Bump version to 2.1.9
// FREEBIE
2014-10-13 19:02:37 -07:00
Moxie Marlinspike
2c8c6a410c Updated language translations.
// FREEBIE
2014-10-13 18:11:20 -07:00
Jake McGinty
2075bba86c switch back to BufferedInputStream
// FREEBIE
2014-10-13 15:38:27 -07:00
Jake McGinty
1d7b47c982 add CM APN list, remove non-MMS APN info
Fixes missing Verizon APN. Overall, smaller DB size but more APN info.
// FREEBIE
2014-10-13 12:33:54 -07:00
Jake McGinty
89fb80fcc5 MmsConnection refactor
- Use Apache HttpClient v4.x, only library that seems to like HTTP proxies
- Remove custom redirect logic in favor of library's

Fixes #1904
// FREEBIE
2014-10-13 12:26:38 -07:00
Moxie Marlinspike
f1d230ce6e Merge pull request #1964 from mcginty/maven-https
use https maven central
2014-10-01 17:16:11 -07:00
Jake McGinty
f51a5aa7eb use https maven central
// FREEBIE
2014-09-30 21:46:13 -07:00
Moxie Marlinspike
cf9c9bbfd7 Bumping version to 2.1.8
// FREEBIE
2014-09-15 19:34:30 -07:00
Jake McGinty
b8a3e87f3d custom redirect logic
// FREEBIE
2014-09-15 14:13:27 -07:00
Moxie Marlinspike
e5bad2746f Merge pull request #1917 from mcginty/mccmnc-crash
don't crash if we can't get an mccmnc
2014-09-15 09:32:28 -07:00
Jake McGinty
7316f17674 don't crash if we can't get an mccmnc
Fixes #1916
// FREEBIE
2014-09-14 17:46:07 -07:00
Veeti Paananen
609e69a801 Show date and year for ancient (> 1 year old) messages
The timestamp shown for very old messages only includes the time without
a date at all. Fix it. FREEBIE.
2014-09-08 15:08:46 -07:00
Moxie Marlinspike
d979593cbb Bump version to 2.1.7 2014-09-06 15:38:55 -07:00
Moxie Marlinspike
0808e00d0e Updated translations.
// FREEBIE
2014-09-06 14:54:32 -07:00
Moxie Marlinspike
2045c828be Merge pull request #1892 from mcginty/bitmap-memory
fallback to imprecise scaling if low memory
2014-09-06 14:53:56 -07:00
Jake McGinty
1b3bd32805 fallback to rough scaling if low memory
// FREEBIE
2014-09-05 13:00:26 -07:00
Moxie Marlinspike
877f2a25a9 Merge pull request #1887 from mcginty/mms-3xx
allow url client to follow redirects before checking response code
2014-08-29 15:23:00 -07:00
Jake McGinty
eb462f0345 force redirects, get inputstream first 2014-08-29 16:34:25 -05:00
Moxie Marlinspike
102b40543d Merge pull request #1886 from mcginty/mms-bad-pdu-logging
enable more verbose PDU parse logging
2014-08-29 14:33:25 -07:00
Jake McGinty
12077c6dad enable more verbose PDU parse logging
// FREEBIE
2014-08-29 16:29:36 -05:00
Jake McGinty
7441c191a7 Format outgoing MMS using SMIL.
// FREEBIE

Closes #1879
2014-08-29 14:29:24 -07:00
Lukas Barth
b355991b0b Remove superfluous repetition
//FREEBIE
2014-08-29 15:33:19 +02:00
Moxie Marlinspike
350eb438c0 Bump version to 2.1.6
// FREEBIE
2014-08-20 16:48:12 -07:00
Moxie Marlinspike
da7bbf4144 Merge pull request #1862 from mcginty/db-localization-ignore
disable localized collators in ApnDB
2014-08-20 14:39:50 -07:00
Jake McGinty
a0842f329f disable localized collators in ApnDB
// FREEBIE
2014-08-20 13:41:59 -07:00
Moxie Marlinspike
567224b4a6 Merge pull request #1861 from mcginty/cursor-leak
prevent another cursor leak
2014-08-20 12:32:24 -07:00
Jake McGinty
9b495d8c83 prevent another cursor leak
// FREEBIE
2014-08-20 12:29:40 -07:00
Moxie Marlinspike
8c55ea09d9 Updated language translations.
// FREEBIE
2014-08-20 10:53:16 -07:00
Moxie Marlinspike
5264ebed67 Avoid leaking cursor.
// FREEBIE

Closes #1838
2014-08-20 10:36:39 -07:00
Jake McGinty
7f51f9fd5b apntool and ApnDatabase
// FREEBIE
2014-08-20 10:36:39 -07:00
Moxie Marlinspike
40495a2261 Merge pull request #1854 from mcginty/content-description
improve some content descriptions
2014-08-19 21:00:20 -07:00
Jake McGinty
a6c1fdd914 improve some content descriptions
// FREEBIE
2014-08-19 19:10:15 -07:00
Jake McGinty
020d61dd6e migrate nav panel items to actionbar
Fixes #1819
Closes #1839
// FREEBIE
2014-08-19 15:20:57 -07:00
Jake McGinty
dee23b266f update support-v4 library
Fixes #1832
// FREEBIE
2014-08-14 23:29:25 -07:00
Moxie Marlinspike
4cf57fbb55 Bump version to 2.1.5
// FREEBIE
2014-08-13 16:47:47 -07:00
Moxie Marlinspike
85da05397a Update language translations.
// FREEBIE
2014-08-13 15:14:08 -07:00
Moxie Marlinspike
f4e9c4a710 Minor MMS cleanup.
// FREEBIE

Closes #1827
2014-08-13 14:40:19 -07:00
Jake McGinty
28e14f47cf use URLConnection for MMS because it's better
// FREEBIE
2014-08-13 12:36:47 -07:00
Jake McGinty
d2edda837a Update Play services and add checksum
Quoting Google employee: "5.0.77 had some serious issues, team didn't want
anyone using it"

// FREEBIE
2014-08-12 20:12:52 -07:00
Jake McGinty
213715a0dc braces around loop, proper spacing
// FREEBIE
2014-08-12 18:23:18 -07:00
Moxie Marlinspike
7b0479ff0f requestRouteToHost of URL rather than MMSC on MMS Download
// FREEBIE

Closes #1806
2014-08-12 17:31:28 -07:00
rymdhund
feabbb33d2 MMS Fixes
1) Respect proxyIfPossible flag and make sure to try all mms APNs

2) Reorder mmsc connection process
2014-08-12 17:30:19 -07:00
rymdhund
d3da409774 Add time to saved media filenames
see #1689
// FREEBIE
2014-08-12 16:09:26 -07:00
Moxie Marlinspike
edb04138c2 Merge pull request #1825 from mcginty/resource-removal
remove old, unused resources
2014-08-12 13:57:49 -07:00
Jake McGinty
8bf537bb09 remove old, unused resources
// FREEBIE
2014-08-12 12:12:08 -07:00
Moxie Marlinspike
b80593b5f5 Merge pull request #1821 from mcginty/mms-npe
prevent MMS notification NPE
2014-08-11 11:08:44 -07:00
Jake McGinty
b61e7839f4 prevent MMS notification NPE
// FREEBIE
2014-08-10 21:15:55 -07:00
Drew Hintz
7b41b1492e Shrink png files using pngout. Saves 608kB. FREEBIE. 2014-08-07 17:56:08 -07:00
Moxie Marlinspike
928b9687ef Bump version to 2.1.4
// FREEBIE
2014-08-04 20:48:02 -07:00
Jake McGinty
306c127803 fix EmojiLRU concurrency exception
// FREEBIE
2014-08-04 16:51:44 -07:00
Jake McGinty
239a11bfd2 fix unused argument
// FREEBIE
2014-08-04 15:30:52 -07:00
Jake McGinty
de63b0dd96 make reminder a custom view, make push reminder
// FREEBIE
2014-08-04 15:25:53 -07:00
Jake McGinty
eb4ac40051 don't use old emoji recents, broken
Fixes #1782
// FREEBIE
2014-08-04 15:23:43 -07:00
Moxie Marlinspike
dda4459e5a Bump version to 2.1.3
// FREEBIE
2014-08-02 23:43:45 -07:00
Moxie Marlinspike
8726dd51be Can't toast on this thread.
// FREEBIE
2014-08-02 23:15:57 -07:00
Moxie Marlinspike
e53bbe8453 Bumping version to 2.1.2
// FREEBIE
2014-08-01 16:14:02 -07:00
Moxie Marlinspike
ecb67cd84f Updated language translations.
// FREEBIE
2014-08-01 14:41:00 -07:00
Moxie Marlinspike
861d27279d Whoops, add GcmRegistrationService to Manifest.
// FREEBIE
2014-08-01 14:33:17 -07:00
Veeti Paananen
bef5b8f3e9 Occupy all vertical space for emoji grid
Fixes the recent emoji list leaving an empty gap at the bottom of the
drawer depending on the number of items shown.
2014-08-01 13:40:19 -07:00
Veeti Paananen
9e74b5c892 Remove gray placeholder squares while loading emoji 2014-08-01 13:40:19 -07:00
Veeti Paananen
3597915d17 Add a backspace key to the emoji drawer 2014-08-01 13:40:19 -07:00
Veeti Paananen
40ce0cebe0 Fix emoji backwards compatibility recents crash
The old emoji drawer stored emoji with a .png suffix. Replace it during
list deserialization.
2014-07-31 02:49:36 +03:00
jhertel
26d58047b5 Update BUILDING.md
Correction of a typo and a few style incongruences.

// FREEBIE
Closes #1750
2014-07-28 09:36:03 -07:00
Jake McGinty
7d688846f9 Move default SMS and system import to "reminders"
// FREEBIE
Closes #1730
2014-07-27 01:09:39 -07:00
McLoo
acc7c4c1c6 Null check for cipher text to prevent NPE on decryption
Fixes #1703
Closes #1728
// FREEBIE
2014-07-26 23:02:11 -07:00
Jake McGinty
530ad7bc86 new emoji drawer
// FREEBIE
Closes #1746
2014-07-26 13:35:03 -07:00
Jake McGinty
bea3c33223 disable passphrase creation on registration
// FREEBIE
Closes #1726
2014-07-25 17:46:50 -07:00
Moxie Marlinspike
9ef14a0f64 Upgrade to new GCM API. 2014-07-23 15:40:45 -07:00
Moxie Marlinspike
c632b32ff8 Bumping version to 2.1.1 2014-07-19 11:13:18 -07:00
Moxie Marlinspike
40698212bb Create a Curve25519 asymmetric master secret for users without.
Fixes #1701
2014-07-18 22:16:12 -07:00
Veeti Paananen
19ae5043cc Add number of messages to the notification number attribute
Although not used by stock Android, many custom ROM's (and possibly OEM
versions?) have a setting to display the "number" count of a notification
overlayed on the status bar icon. Add support for this.

Closes #1637
2014-07-16 11:50:42 -07:00
rymdhund
d1dd50e31c Add date to saved media filenames
Fixes #1689
Closes #1693
2014-07-16 11:46:18 -07:00
Jake McGinty
23a1c1c8fa Upgrade to latest Android gradle plugin
// FREEBIE
Closes #1660
2014-07-16 11:12:51 -07:00
Moxie Marlinspike
3a62a8b428 Bumping version to 2.1.0 2014-07-15 10:05:15 -07:00
Moxie Marlinspike
cfac27645b Update language translations.
// FREEBIE
2014-07-14 18:44:34 -07:00
Jake McGinty
f6e04d0f89 use latest android number as recipient number
Fixes #791
// FREEBIE
2014-07-14 16:22:15 -07:00
Jake McGinty
61d18f49ad Merge pull request #1678 from veeti/check-icon
Add xxhdpi check drawable for notifications
2014-07-07 16:09:44 -05:00
Veeti Paananen
f26f89d63d Add xxhdpi check drawable for notifications
Fixes blurry mark as read icon on Android Wear. FREEBIE.
2014-07-05 02:40:00 +03:00
Moxie Marlinspike
66aad852f8 Merge pull request #1642 from mcginty/canonical-bunk-addresses
don't try to load recipients for each filter text
2014-06-25 08:06:00 -07:00
Jake McGinty
da0eb5a779 no longer load a recipient for each filter text
// FREEBIE
2014-06-24 20:33:04 -07:00
Jake McGinty
a82d2dfc5c Revert "change out key cached icon to be more unique"
This reverts commit d6d76fa953.
2014-06-24 19:20:16 -07:00
McLoo
d429f9113b Replace XML serializer in plaintext export
Fixes #342

- using regex pattern/matcher to escape chars below 0x0020 and
  above 0xd7ff
- using String.Replace to escape XML entities
- changed XmlPullParser from Xml.newPullParser() to
  XmlPullParserFactory parser to fix import on GB
2014-06-24 13:02:36 -07:00
Moxie Marlinspike
8f85eb1822 Remove unused files.
Fixes #1522

// FREEBIE
2014-06-24 08:32:59 -07:00
Moxie Marlinspike
358c923891 Merge pull request #1630 from mcginty/remove-keys-list
remove ReviewIdentitiesActivity
2014-06-23 11:17:17 -07:00
Lukas Barth
2d9cd8eb52 Fixing race condition and other mistakes. Fixes #1603.
// FREEBIE
2014-06-23 11:16:37 -07:00
Moxie Marlinspike
db1d846833 Merge pull request #1631 from mcginty/disable-encrypted-export
temporarily disable encrypted backup
2014-06-23 07:18:50 -07:00
Jake McGinty
5121ab0eed temporarily disable encrypted backup
// FREEBIE
2014-06-22 16:40:02 -07:00
Jake McGinty
f63f95404e remove ReviewIdentitiesActivity
// FREEBIE
2014-06-22 16:21:30 -07:00
Jake McGinty
622d8975fc add section about submitting useful bug reports 2014-06-20 12:24:36 -07:00
Moxie Marlinspike
81365eff36 Merge pull request #1614 from mcginty/contact-list-security
move FLAG_SECURE to PassphraseRequiredMixin
2014-06-17 21:47:00 -07:00
Florian Walch
453610c39f Add Travis CI config.
//FREEBIE
2014-06-17 14:13:42 -07:00
Jake McGinty
5ce6dc954a move FLAG_SECURE to PassphraseRequiredMixin
Fixes #1402
// FREEBIE
2014-06-16 20:41:13 -07:00
Özgür Emir
c85a8bbb38 Always show the time of the received message. 2014-06-16 15:57:39 -07:00
agrajaghh
0f9a6e6296 add custom phone number type 2014-06-16 15:27:33 -07:00
phenx-de
d8cb893681 Fixes "subtitle is not updated when select all is pressed"
// FREEBIE
2014-06-16 09:33:35 -07:00
Michael Kaiser
1ad54e7b88 Fix more leaked service connections
PassphraseRequiredMixin might check for a bound service at a time where
the bind has been requested but the service connection has not been
established yet, and therefore fail to call unbindService, leading to a
leaked service connection. This fixes #1518.
2014-06-15 19:28:09 -07:00
Moxie Marlinspike
0d35e2bfa9 Fix the "Tap for X fallback" labels. 2014-06-13 17:48:56 -07:00
Moxie Marlinspike
983bf672cf Fix UI side of broken MMS fallback.
1) Actually tell the SendReceiveService to send the MMS if it is
   one.

2) Display the correct string (SMS vs MMS) in the fallback dialog.
2014-06-13 17:39:29 -07:00
Moxie Marlinspike
1c2e1a07f5 Fixes for outgoing SMS/MMS direct and fallback behavior.
1) Correct MMS fallback settings.

2) Prevent SMS/MMS messages from leaking out under certain
   circumstances when they shouldn't.
2014-06-13 17:15:46 -07:00
Moxie Marlinspike
2d739a324e Validate MMS delivery destination.
We can't depend on validated Recipients anymore, so this adds
parity to the validation the SMS transport does now.

Fixes #1592
2014-06-13 16:15:33 -07:00
Moxie Marlinspike
ba1055df8e Correct contextual send language.
1) Use "secure" and "insecure" vs "encrypted" and "unencrypted.

2) Use MMS instead of SMS where appropriate.

Fixes #1602
2014-06-13 15:24:38 -07:00
phenx-de
a54d20f3ef Add "%s selected" subtitle to Conversation List batch mode. 2014-06-13 09:35:36 -07:00
phenx-de
ea0fa58265 Add preview of encryption channel in compose text hint. 2014-06-12 16:32:31 -07:00
Moxie Marlinspike
359fe280e8 Fix for broken build (*ahem* @phenx-de *ahem*) =)
// FREEBIE
2014-06-12 16:27:51 -07:00
Jake McGinty
34e147838a use apply for preferences instead of commit
// FREEBIE
2014-06-12 14:45:51 -07:00
phenx-de
d8e6a93584 Use contextual action bar menu for conversation items. 2014-06-12 14:27:34 -07:00
phenx-de
5ae8a7a8c4 Improved the warning icon: Higher resolution, better size. 2014-06-12 14:24:08 -07:00
Moxie Marlinspike
0e6773b4b7 Remove directory refresh preference.
This is present on the contact screen now, so there's no longer
any need for it here.
2014-06-12 11:58:24 -07:00
McLoo
fb13d33e2e Show drafts emojified when Android version is below KitKat 2014-06-12 11:30:50 -07:00
Pascal Hartig
92fd8ededd Sort contacts case-insentively
This fixes the case sensitive ordering of contacts in the view
for creating new conversations.

Fix #1502
2014-06-12 10:56:46 -07:00
agrajaghh
8713a85beb Add notification for key change event.
Fixes #1460
2014-06-12 10:40:46 -07:00
Marek Wehmer
9b82411c3d Better share intent handling.
1) Guess mime type from share intent EXTRA_STREAM uri.

2) Always include EXTRA_TEXT (if present)
2014-06-12 10:23:56 -07:00
Jake McGinty
16764f74fe reorganize readme
// FREEBIE
2014-06-12 10:02:18 -07:00
Veeti Paananen
bd889d8fa9 Reword the very confusing screen security setting 2014-06-12 09:22:39 -07:00
Moxie Marlinspike
d51adab76b Use "date sent" as timestamp for push, "date received" for SMS.
The "sent time" is not reliable on SMS messages.  This switches
to using "sent time" by default for push messages, but "received
time" for SMS messages.
2014-06-12 08:59:54 -07:00
Chris V
b990202468 Allow passphrase unlock from "unlock" keyboard action. 2014-06-11 21:45:03 -07:00
Pascal Hartig
7208018097 Clear search when opening the drawer
Before this change opening the drawer while a filter was active
would hide the search bar but keep the conversation list filtered,
so there was no indication of an active filter.
2014-06-11 18:12:07 -07:00
Moxie Marlinspike
c719a48a2c Move media attachment long-click event to context menu.
Long-click on a media attachment will now bring up the normal
context menu for a ConversationItem long-click, but with the
addition of a "save attachment" option.

This allows users to long-click on messages with media in them
and still see the other contextual menu options.

// FREEBIE
2014-06-11 18:04:14 -07:00
Moxie Marlinspike
68747142d6 Add correct contextual menu options on 'Send' button.
[Send TextSecure message | Send unencrypted SMS | Send encrypted SMS]

// FREEBIE
2014-06-11 15:34:01 -07:00
Lukas Barth
7c9282f306 Cache circle cropped photos on Recipient. 2014-06-11 12:33:57 -07:00
Lukas Barth
fa3cb871d0 Use ACTION_OPEN_DOCUMENT for Android >= KitKat.
Fixes #926.

We have to do this, since with the new Storage Access Framework,
otherwise we can open the Uri only *once*. This would work well
unless someone saves a draft and goes back to the conversation -
then the Uri is opened again without the required permissions.

See:

https://developer.android.com/guide/topics/providers/document-provider.html#client

...for details.
2014-06-11 11:58:55 -07:00
Moxie Marlinspike
a19899a11f Merge pull request #1589 from jlund/cyanogen-error-message
Fixing a typo in the WhisperPush error message
2014-06-11 09:20:50 -07:00
Joshua Lund
667da3b2cf Fixing a typo in the WhisperPush error message
// FREEBIE
2014-06-10 20:56:45 -06:00
Moxie Marlinspike
1a86483b7f Merge pull request #1581 from mcginty/android-studio-060
Upgrade android plugin to stay compatible with latest Android Studio
2014-06-10 09:07:59 -07:00
Jake McGinty
de90222c95 Upgrade android plugin to stay compatible with latest Android Studio
// FREEBIE
2014-06-09 23:31:52 -07:00
Moxie Marlinspike
7cf84e904a Merge pull request #1573 from Jabro/master
Added APN Settings for T-Mobile UK
2014-06-09 09:44:50 -07:00
Jabro
12e92b9cdf Added APN Settings for T-Mobile UK
Fixes #1558
2014-06-09 12:43:19 +02:00
Moxie Marlinspike
4153c8dae9 No need to verify a local module.
// FREEBIE
2014-06-06 09:14:43 -07:00
Moxie Marlinspike
ef72702f0d Include gradle-witness plugin for verifying dependencies. 2014-06-05 10:19:28 -07:00
Moxie Marlinspike
f5e2010455 Merge pull request #1554 from thoughtbox/patch-8
Capitalisation according to Android guidelines
2014-06-05 09:06:19 -07:00
thoughtbox
bc769debe2 Capitalisation according to Android guidelines
Not all updated capitalisations were correct.
2014-06-05 09:24:31 +02:00
Moxie Marlinspike
df1c96a662 Do country code detection if we can't get the full number off SIM. 2014-06-03 19:16:27 -07:00
Corbin Souffrant
db356a0ec9 Fixed capitalization inconsistensies with Android guidelines.
Fixes #673
2014-06-03 18:51:21 -07:00
Michael Bennett
468eb3382c Add sorting by default phone number
Currently the order of numbers is times contacted -> displayName ->
phone type (mobile vs. home, etc.). This adds whether the number has
been saved as the default number for a contact to sort numbers belonging
to the same contact.

Fixes #580
2014-06-03 18:18:41 -07:00
Moxie Marlinspike
12d217991c Use dynamic PBE iteration count.
Fixes #184
Fixes #247
2014-06-03 17:59:11 -07:00
Ruben Pollan
5785860631 Support for multiple APN settings on the same provider 2014-06-03 16:24:20 -07:00
Moxie Marlinspike
addea8d340 Validate recipients at send time rather than when constructed.
Fixes #665
2014-06-03 14:58:19 -07:00
Moxie Marlinspike
59899b1caf Merge pull request #1550 from mcginty/email-send-fix
send email addresses as mms
2014-06-03 12:46:08 -07:00
Jake McGinty
829097d891 send email addresses as mms
// FREEBIE
2014-06-03 12:35:56 -07:00
Moxie Marlinspike
d95bb21065 More ideology.
// FREEBIE
2014-06-01 17:05:21 -07:00
Moxie Marlinspike
0fbe765447 Expand ideology.
//FREEBIE
2014-06-01 10:22:31 -07:00
Moxie Marlinspike
f190321e40 Add some ideology to contributing.md
//FREEBIE
2014-05-31 15:05:59 -07:00
Michael Kaiser
1cb4d479f1 Finish activity before restarting it
The current activity needs to be finished before calling startActivity.
Otherwise, activities with launchMode singleTask (ConversationListActivity)
will receive a new Intent instead of getting restarted. And in response
to the new Intent, they will run onResume once again and trigger a second restart.

Fixes #1292
2014-05-20 10:16:48 -07:00
McLoo
023d776e96 Reactivate a group if a contact gets readded
Fixes #723 //FREEBIE

Removes the own number from group on leaving, to receive a proper
re-added message
2014-05-19 13:18:28 -07:00
Jake McGinty
ce7b8ab75a new passphrase prompt activity
// FREEBIE
2014-05-19 12:16:42 -07:00
agrajaghh
82bb0c07e8 Fix AlertDialog Background on Android 2.3 2014-05-16 17:18:57 -07:00
Manuel
d8d5848dae Change draw selector to background 2014-05-16 11:43:47 -07:00
Jake McGinty
542e1984c1 sanely handle duplicate contacts in db
// FREEBIE
2014-05-16 09:16:20 -07:00
Jake McGinty
dff6997a65 don't call replace() on null formattedNumber
Fixes #1397
// FREEBIE
2014-05-16 09:13:50 -07:00
Moxie Marlinspike
5bfe64752e Merge pull request #1495 from mcginty/icon-cached
change out key cached icon to be more unique
2014-05-16 08:30:31 -07:00
Jake McGinty
d6d76fa953 change out key cached icon to be more unique
Fixes #651
// FREEBIE
2014-05-14 17:52:49 -07:00
Sebastian
03ecd79fe0 fix receiving utf-8 characters in multimedia push messages
Throw AssertionError instead of logging and trying to recover
2014-05-01 15:06:44 -07:00
Moxie Marlinspike
7a3d509ef4 Merge pull request #1437 from mcginty/mms-npe
prevent NPE in MMS logic
2014-05-01 13:05:01 -07:00
Jake McGinty
7a54f33f68 Merge pull request #1354 from agrajaghh/fix_empty_contact_filter
Fix empty contact filter not working properly
2014-05-01 14:18:25 -05:00
Jake McGinty
d4b4667d5a prevent NPE in MMS logic
Fixes #1434
// FREEBIE
2014-04-28 14:05:05 -07:00
thoughtbox
08d899e2e1 Slightly more verbose "no legacy support" message. 2014-04-28 11:02:48 -07:00
Jake McGinty
716519f4b8 Merge pull request #1383 from jocelynthode/master
Add time to messages when they are within the week
2014-04-27 19:19:49 -07:00
Moxie Marlinspike
02d3760b31 Merge pull request #1368 from mcginty/contact-select-header-dark
fix contact selection header theming
2014-04-24 18:47:13 -07:00
Jocelyn Thode
521fbc77c6 Add time to messages when they are within the week
//FREEBIE
2014-04-17 16:10:27 +02:00
Moxie Marlinspike
0574ec170a Display legacy message error when V1 message is received. 2014-04-16 11:47:51 -07:00
Moxie Marlinspike
cebad39422 Collapse some v2 interfaces now that there's no v1. 2014-04-16 11:47:51 -07:00
Moxie Marlinspike
1d07ca3e6f Remove V1 code. 2014-04-16 11:47:51 -07:00
Moxie Marlinspike
ca8c950553 Bump version to 2.0.8
// FREEBIE
2014-04-15 15:59:47 -07:00
Jake McGinty
7349378d8d fix contact selection header theming
Fixes #1343
// FREEBIE
2014-04-14 17:43:13 -07:00
Moxie Marlinspike
dc9a9b14b2 Merge pull request #1367 from mcginty/routing-undo
revert RoutingActivity flags
2014-04-14 15:02:42 -07:00
Jake McGinty
df9afc4e7f revert RoutingActivity flags
// FREEBIE
2014-04-14 14:49:15 -07:00
agrajaghh
e9a50ce6c3 fix empty contact filter 2014-04-13 15:00:04 +02:00
Moxie Marlinspike
4d52d2ee36 Bumping version to 2.0.7 2014-04-11 10:58:39 -07:00
Moxie Marlinspike
c21e5b74f1 Updated language translations. 2014-04-11 10:13:23 -07:00
Moxie Marlinspike
c5b3b27c49 Merge pull request #1339 from mcginty/broken-build
fix old code breaking build
2014-04-11 10:13:05 -07:00
Jake McGinty
ccb0cc6baf fix old code breaking build
// FREEBIE
2014-04-11 10:00:30 -07:00
Moxie Marlinspike
ef77dc9d6d Merge pull request #1324 from mcginty/actionbar-cleanup
use normal means to set actionbar icon
2014-04-10 17:57:53 -07:00
Jake McGinty
454673cd0c Update ActionBar title on language change
Fixes #1329
// FREEBIE
2014-04-10 17:55:03 -07:00
Jake McGinty
0dc6ec294b use normal means to set actionbar icon
// FREEBIE
2014-04-10 17:52:58 -07:00
Santoso Wijaya
12dac6ccc3 ShareActivity, destruction of RecipientsPanel
// FREEBIE
2014-04-10 13:16:14 -07:00
Jake McGinty
e2f7c1529a group and contact list fixes
1) Updating a group without changing the avatar will keep that
   avatar

2) Prohibit adding non-push users to an existing push group

3) Add Android contacts to the same database. Takes a small amount
   more time and memory, but allows queries to not be a hack, and
   enables us to dedupe numbers in JB and higher devices.

// FREEBIE
2014-04-10 11:14:06 -07:00
Jake McGinty
b715debefc mark auto-fallback to sms as forcedSms
// FREEBIE
2014-04-10 10:50:35 -07:00
Moxie Marlinspike
4438b4ae69 Add a TrustManager that blacklists via serial numbers. 2014-04-09 20:50:32 -07:00
Jake McGinty
7b3f2c169a Fix issue with weird exiting animation from conversation
Fixes #1312
// FREEBIE
2014-04-08 10:57:17 -07:00
Matt Enright
7ceaf59bcc Display send date for incoming messages
Fixes #597.
2014-04-05 14:39:58 -07:00
Moxie Marlinspike
4caff2e511 Merge pull request #1297 from McLoo/master
Stop recycled bitmap crashes
2014-04-05 13:38:45 -07:00
McLoo
5e8e13ed5a Stop recycled bitmap crashes
Fixes #792
2014-04-04 23:49:12 +02:00
1152 changed files with 80294 additions and 31756 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.ai binary

7
.travis.yml Normal file
View File

@@ -0,0 +1,7 @@
language: android
android:
components:
- platform-tools
- build-tools-19.1.0
- android-19
- extra-android-m2repository

View File

@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
lang_map = fr_CA:fr-rCA,pt_BR:pt-rBR,pt_PT:pt,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW,da_DK:da-rDK,de_DE:de,tr_TR:tr,fr_FR:fr,es_ES:es,hu_HU:hu,sv_SE:sv-rSE,bg_BG:bg,el_GR:el,kn_IN:kn-rIN,cs_CZ:cs
lang_map = fr_CA:fr-rCA,pt_BR:pt-rBR,pt_PT:pt,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW,da_DK:da-rDK,de_DE:de,tr_TR:tr,fr_FR:fr,es_ES:es,hu_HU:hu,sv_SE:sv-rSE,bg_BG:bg,el_GR:el,kn_IN:kn-rIN,cs_CZ:cs,sr:sr
[textsecure-official.master]

View File

@@ -2,10 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.thoughtcrime.securesms"
android:versionCode="69"
android:versionName="2.0.6">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19"/>
android:versionCode="87"
android:versionName="2.3.3">
<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"
android:label="Access to TextSecure Secrets"
@@ -33,18 +31,20 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="org.thoughtcrime.securesms.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="org.thoughtcrime.securesms.permission.C2D_MESSAGE" />
<application android:name="org.thoughtcrime.securesms.ApplicationListener"
<application android:name=".ApplicationContext"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@style/TextSecure.LightTheme">
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity android:name=".RoutingActivity"
android:theme="@style/NoAnimation.Theme.BlackScreen"
android:launchMode="singleTask"
@@ -71,7 +71,7 @@
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
<data android:mimeType="video/*" />
</intent-filter>
</intent-filter>
</activity>
@@ -93,11 +93,18 @@
<activity android:name=".MmsPreferencesActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ConversationListActivity"
android:label="@string/app_name"
<activity android:name=".ShareActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:noHistory="true"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ConversationListActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ConversationActivity"
android:windowSoftInputMode="stateUnchanged"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -107,27 +114,27 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DatabaseMigrationActivity"
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
android:theme="@style/NoAnimation.Theme.AppCompat.Light.DarkActionBar"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DatabaseUpgradeActivity"
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
android:theme="@style/NoAnimation.Theme.AppCompat.Light.DarkActionBar"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".PassphraseCreateActivity"
android:label="@string/AndroidManifest__create_passphrase"
android:windowSoftInputMode="stateUnchanged"
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
android:theme="@style/TextSecure.IntroTheme"
android:launchMode="singleTop"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".PassphrasePromptActivity"
android:label="@string/AndroidManifest__enter_passphrase"
android:launchMode="singleTop"
android:theme="@style/NoAnimation.Theme.Sherlock.Light.DarkActionBar"
android:windowSoftInputMode="stateUnchanged"
android:theme="@style/TextSecure.IntroTheme"
android:windowSoftInputMode="stateAlwaysVisible"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ContactSelectionActivity"
@@ -165,11 +172,7 @@
android:label="@string/AndroidManifest__verify_identity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ReviewIdentitiesActivity"
android:label="@string/AndroidManifest__manage_identity_keys"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".ReceiveKeyActivity"
<activity android:name=".ReceiveKeyActivity"
android:label="@string/AndroidManifest__complete_key_exchange"
android:theme="@style/TextSecure.Light.Dialog"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
@@ -189,6 +192,11 @@
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".MediaPreviewActivity"
android:label="@string/AndroidManifest__media_preview"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".DummyActivity"
android:theme="@android:style/Theme.NoDisplay"
android:enabled="true"
@@ -200,13 +208,14 @@
android:clearTaskOnLaunch="true"
android:finishOnTaskLaunch="true" />
<activity android:name=".PlayServicesProblemActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<service android:enabled="true" android:name=".service.ApplicationMigrationService"/>
<service android:enabled="true" android:name=".service.KeyCachingService"/>
<service android:enabled="true" android:name=".service.SendReceiveService"/>
<service android:enabled="true" android:name=".service.RegistrationService"/>
<service android:enabled="true" android:name=".service.DirectoryRefreshService"/>
<service android:enabled="true" android:name=".service.PreKeyService"/>
<service android:enabled="true" android:name=".gcm.GcmIntentService"/>
<service android:name=".service.QuickResponseService"
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE"
@@ -233,7 +242,6 @@
<receiver android:name=".gcm.GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="org.thoughtcrime.securesms" />
</intent-filter>
</receiver>
@@ -299,8 +307,4 @@
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="org.thoughtcrime.securesms.tests" android:label="Tests for My App" />
</manifest>

View File

@@ -17,7 +17,11 @@ The following steps should help you (re)build TextSecure from the command line.
git clone https://github.com/WhisperSystems/TextSecure.git
2. Make sure you have the [Android SDK](https://developer.android.com/sdk/index.html) installed somewhere on your system.
3. Ensure the "Android Support Repository" and "Android SDK Build-tools" are installed from the Android SDK manager.
3. Ensure that the following packages are installed from the Android SDK manager:
* Android SDK Build Tools
* SDK Platform
* Android Support Repository
* Google Repository
4. Create a local.properties file at the root of your source checkout and add an sdk.dir entry to it.
sdk.dir=\<path to your sdk installation\>
@@ -29,13 +33,13 @@ The following steps should help you (re)build TextSecure from the command line.
Re-building native components
-----------------------------
Note: This step is optional; native components are contained as binaries (see [library/libs](library/libs)).
Note: This step is optional; native components are contained as binaries (see [libaxolotl/libs](libaxolotl/libs)).
1. Ensure that the Android NDK is installed.
Execute ndk-build:
cd library
cd libaxolotl
ndk-build
Afterwards, execute Gradle as above to re-create the APK.
@@ -45,12 +49,12 @@ Setting up a development environment
[Android Studio](https://developer.android.com/sdk/installing/studio.html) is the recommended development environment.
1. Install Android Studio
1. Install Android Studio.
2. Make sure the "Android Support Repository" is installed in the Android Studio SDK.
3. Make sure the latest "Android SDK build-tools" is installed in the Android Studio SDK.
4. Create a new Android Studio project. from the Quickstart pannel (use File > Close Project to see it), choose "Checkout from Version Control" then "git".
5. Paste the URL for the TextSecure project when prompted (https://github.com/WhisperSystems/TextSecure.git)
6. Android studio should detect the presence of a project file and ask you wethere to open it. Click "yes".
5. Paste the URL for the TextSecure project when prompted (https://github.com/WhisperSystems/TextSecure.git).
6. Android studio should detect the presence of a project file and ask you whether to open it. Click "yes".
7. Default config options should be good enough.
8. Project initialisation and build should proceed.

View File

@@ -1,73 +1,73 @@
TextSecure
=================
# TextSecure [![Build Status](https://travis-ci.org/WhisperSystems/TextSecure.svg?branch=master)](https://travis-ci.org/WhisperSystems/TextSecure)
A secure text messaging application for Android.
TextSecure is a messaging app for easy private communicate with friends.
TextSecure is a replacement for the standard text messaging application, allowing you to send and receive text messages as normal. Additionally, TextSecure provides:
TextSecure can use either data (WiFi/3G/4G) or SMS to communicate securely, and all TextSecure
messages can also be encrypted locally on your device.
1. *Local Encryption* -- All text messages, regardless of destination, that are sent or received with TextSecure are stored in an encrypted database on your phone.
2. *Wire Encryption* -- When communicating with a recipient who is also using TextSecure, text messages are encrypted during transmission.
Currently available on the Play store.
Current BitHub Payment For Commit:
=================
[![Current Price](https://bithub.herokuapp.com/v1/status/payment/commit/)](https://whispersystems.org/blog/bithub/)
*[![Play Store Badge](https://developer.android.com/images/brand/en_app_rgb_wo_60.png)](https://play.google.com/store/apps/details?id=org.thoughtcrime.securesms)*
Building and contributing code
==============================
Instructions on how to build TextSecure, as well as on how to setup an IDE to modify it can be found in the "BUILDING.md" file.
Bug tracker
-----------
Have a bug? Please create an issue here on GitHub!
## Contributing Bug reports
We use GitHub for bug tracking. Please search the existing issues for your bug and create a new one if the issue is not yet tracked!
https://github.com/WhisperSystems/TextSecure/issues
## Contributing Translations
Interested in helping to translate TextSecure? Contribute here:
Documentation
-------------
https://www.transifex.com/projects/p/textsecure-official/
Looking for documentation? Check out the wiki!
## Contributing Code
Instructions on how to setup your development environment and build TextSecure can be found in [BUILDING.md](https://github.com/WhisperSystems/TextSecure/blob/master/BUILDING.md).
https://github.com/WhisperSystems/TextSecure/wiki
If you're new to the TextSecure codebase, we recommend going through our issues and picking out a simple bug to fix (check the "easy" label in our issues) in order to get yourself familiar.
Mailing list
------------
For larger changes and feature ideas, we ask that you propose it on the mailing list for a high-level discussion before implementation.
Have a question? Ask on our mailing list!
This repository is set up with [BitHub](https://whispersystems.org/blog/bithub/), so you can make money for committing to TextSecure. The current BitHub price for an accepted pull request is:
[![Current BitHub Price](https://bithub.herokuapp.com/v1/status/payment/commit/)](https://whispersystems.org/blog/bithub/)
## Contributing Ideas
Have something you want to say about Open Whisper Systems projects or want to be part of the conversation? Get involved in the mailing list!
whispersystems@lists.riseup.net
https://lists.riseup.net/www/info/whispersystems
Translation
------------
## Contributing Funds
[![Donate](https://coinbase.com/assets/buttons/donation_large-6ec72b1a9eec516944e50a22aca7db35.png)](https://whispersystems.org/blog/bithub/)
Interested in helping to translate TextSecure? Contribute here:
You can add funds to BitHub to directly help further development efforts.
https://www.transifex.com/projects/p/textsecure-official/
Help
====
## Support
For troubleshooting and questions, please visit our support center!
Downloads
------------
http://support.whispersystems.org/
TextSecure can be downloaded from the Play Store here:
## Documentation
Looking for documentation? Check out the wiki!
https://play.google.com/store/apps/details?id=org.thoughtcrime.securesms
https://github.com/WhisperSystems/TextSecure/wiki
Cryptography Notice
------------
# Legal things
## Cryptography Notice
This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software.
BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted.
This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software.
BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted.
See <http://www.wassenaar.org/> for more information.
The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms.
The U.S. Government Department of Commerce, Bureau of Industry and Security (BIS), has classified this software as Export Commodity Control Number (ECCN) 5D002.C.1, which includes information security software using or performing cryptographic functions with asymmetric algorithms.
The form and manner of this distribution makes it eligible for export under the License Exception ENC Technology Software Unrestricted (TSU) exception (see the BIS Export Administration Regulations, Section 740.13) for both object code and source code.
License
---------------------
## License
Copyright 2011 Whisper Systems
Copyright 2013 Open WhisperSystems
Copyright 2013-2014 Open Whisper Systems
Licensed under the GPLv3: http://www.gnu.org/licenses/gpl-3.0.html

View File

@@ -0,0 +1,118 @@
package org.thoughtcrime.securesms.database;
import android.test.InstrumentationTestCase;
import static org.fest.assertions.api.Assertions.assertThat;
public class CanonicalAddressDatabaseTest extends InstrumentationTestCase {
private static final String AMBIGUOUS_NUMBER = "222-3333";
private static final String SPECIFIC_NUMBER = "+49 444 222 3333";
private static final String EMAIL = "a@b.fom";
private static final String SIMILAR_EMAIL = "a@b.com";
private static final String GROUP = "__textsecure_group__!000111222333";
private static final String SIMILAR_GROUP = "__textsecure_group__!100111222333";
private static final String ALPHA = "T-Mobile";
private static final String SIMILAR_ALPHA = "T-Mobila";
private CanonicalAddressDatabase db;
public void setUp() throws Exception {
super.setUp();
this.db = CanonicalAddressDatabase.getInstance(getInstrumentation().getTargetContext());
}
public void tearDown() throws Exception {
}
/**
* Throw two equivalent numbers (one without locale info, one with full info) at the canonical
* address db and see that the caching and DB operations work properly in revealing the right
* addresses. This is run twice to ensure cache logic is hit.
*
* @throws Exception
*/
public void testNumberAddressUpdates() throws Exception {
final long id = db.getCanonicalAddressId(AMBIGUOUS_NUMBER);
assertThat(db.getAddressFromId(id)).isEqualTo(AMBIGUOUS_NUMBER);
assertThat(db.getCanonicalAddressId(SPECIFIC_NUMBER)).isEqualTo(id);
assertThat(db.getAddressFromId(id)).isEqualTo(SPECIFIC_NUMBER);
assertThat(db.getCanonicalAddressId(AMBIGUOUS_NUMBER)).isEqualTo(id);
assertThat(db.getCanonicalAddressId(AMBIGUOUS_NUMBER)).isEqualTo(id);
assertThat(db.getAddressFromId(id)).isEqualTo(AMBIGUOUS_NUMBER);
assertThat(db.getCanonicalAddressId(SPECIFIC_NUMBER)).isEqualTo(id);
assertThat(db.getAddressFromId(id)).isEqualTo(SPECIFIC_NUMBER);
assertThat(db.getCanonicalAddressId(AMBIGUOUS_NUMBER)).isEqualTo(id);
}
public void testSimilarNumbers() throws Exception {
assertThat(db.getCanonicalAddressId("This is a phone number 222-333-444"))
.isNotEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("222-333-444"))
.isNotEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("222-333-44"))
.isNotEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("222-333-4"))
.isNotEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("+49 222-333-4444"))
.isNotEqualTo(db.getCanonicalAddressId("+1 222-333-4444"));
assertThat(db.getCanonicalAddressId("1 222-333-4444"))
.isEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("1 (222) 333-4444"))
.isEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("+12223334444"))
.isEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("+1 (222) 333.4444"))
.isEqualTo(db.getCanonicalAddressId("222-333-4444"));
assertThat(db.getCanonicalAddressId("+49 (222) 333.4444"))
.isEqualTo(db.getCanonicalAddressId("222-333-4444"));
}
public void testEmailAddresses() throws Exception {
final long emailId = db.getCanonicalAddressId(EMAIL);
final long similarEmailId = db.getCanonicalAddressId(SIMILAR_EMAIL);
assertThat(emailId).isNotEqualTo(similarEmailId);
assertThat(db.getAddressFromId(emailId)).isEqualTo(EMAIL);
assertThat(db.getAddressFromId(similarEmailId)).isEqualTo(SIMILAR_EMAIL);
}
public void testGroups() throws Exception {
final long groupId = db.getCanonicalAddressId(GROUP);
final long similarGroupId = db.getCanonicalAddressId(SIMILAR_GROUP);
assertThat(groupId).isNotEqualTo(similarGroupId);
assertThat(db.getAddressFromId(groupId)).isEqualTo(GROUP);
assertThat(db.getAddressFromId(similarGroupId)).isEqualTo(SIMILAR_GROUP);
}
public void testAlpha() throws Exception {
final long id = db.getCanonicalAddressId(ALPHA);
final long similarId = db.getCanonicalAddressId(SIMILAR_ALPHA);
assertThat(id).isNotEqualTo(similarId);
assertThat(db.getAddressFromId(id)).isEqualTo(ALPHA);
assertThat(db.getAddressFromId(similarId)).isEqualTo(SIMILAR_ALPHA);
}
public void testIsNumber() throws Exception {
assertThat(CanonicalAddressDatabase.isNumberAddress("+495556666777")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("(222) 333-4444")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("1 (222) 333-4444")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("T-Mobile123")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("333-4444")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("12345")).isTrue();
assertThat(CanonicalAddressDatabase.isNumberAddress("T-Mobile")).isFalse();
assertThat(CanonicalAddressDatabase.isNumberAddress("T-Mobile1")).isFalse();
assertThat(CanonicalAddressDatabase.isNumberAddress("Wherever bank")).isFalse();
assertThat(CanonicalAddressDatabase.isNumberAddress("__textsecure_group__!afafafafafaf")).isFalse();
assertThat(CanonicalAddressDatabase.isNumberAddress("email@domain.com")).isFalse();
}
}

View File

@@ -0,0 +1,153 @@
package org.thoughtcrime.securesms.jobs;
import android.test.AndroidTestCase;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.dependencies.AxolotlStorageModule;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
import org.whispersystems.textsecure.api.TextSecureAccountManager;
import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
public class CleanPreKeysJobTest extends AndroidTestCase {
public void testSignedPreKeyRotationNotRegistered() throws IOException, MasterSecretJob.RequirementNotMetException {
TextSecureAccountManager accountManager = mock(TextSecureAccountManager.class);
SignedPreKeyStore signedPreKeyStore = mock(SignedPreKeyStore.class);
MasterSecret masterSecret = mock(MasterSecret.class);
when(accountManager.getSignedPreKey()).thenReturn(null);
CleanPreKeysJob cleanPreKeysJob = new CleanPreKeysJob(getContext());
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(accountManager, signedPreKeyStore));
objectGraph.inject(cleanPreKeysJob);
cleanPreKeysJob.onRun(masterSecret);
verify(accountManager).getSignedPreKey();
verifyNoMoreInteractions(signedPreKeyStore);
}
public void testSignedPreKeyEviction() throws Exception {
SignedPreKeyStore signedPreKeyStore = mock(SignedPreKeyStore.class);
TextSecureAccountManager accountManager = mock(TextSecureAccountManager.class);
SignedPreKeyEntity currentSignedPreKeyEntity = mock(SignedPreKeyEntity.class);
MasterSecret masterSecret = mock(MasterSecret.class);
when(currentSignedPreKeyEntity.getKeyId()).thenReturn(3133);
when(accountManager.getSignedPreKey()).thenReturn(currentSignedPreKeyEntity);
final SignedPreKeyRecord currentRecord = new SignedPreKeyRecord(3133, System.currentTimeMillis(), Curve.generateKeyPair(), new byte[64]);
List<SignedPreKeyRecord> records = new LinkedList<SignedPreKeyRecord>() {{
add(new SignedPreKeyRecord(2, 11, Curve.generateKeyPair(), new byte[32]));
add(new SignedPreKeyRecord(4, System.currentTimeMillis() - 100, Curve.generateKeyPair(), new byte[64]));
add(currentRecord);
add(new SignedPreKeyRecord(3, System.currentTimeMillis() - 90, Curve.generateKeyPair(), new byte[64]));
add(new SignedPreKeyRecord(1, 10, Curve.generateKeyPair(), new byte[32]));
}};
when(signedPreKeyStore.loadSignedPreKeys()).thenReturn(records);
when(signedPreKeyStore.loadSignedPreKey(eq(3133))).thenReturn(currentRecord);
CleanPreKeysJob cleanPreKeysJob = new CleanPreKeysJob(getContext());
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(accountManager, signedPreKeyStore));
objectGraph.inject(cleanPreKeysJob);
cleanPreKeysJob.onRun(masterSecret);
verify(signedPreKeyStore).removeSignedPreKey(eq(1));
verify(signedPreKeyStore, times(1)).removeSignedPreKey(anyInt());
}
public void testSignedPreKeyNoEviction() throws Exception {
SignedPreKeyStore signedPreKeyStore = mock(SignedPreKeyStore.class);
TextSecureAccountManager accountManager = mock(TextSecureAccountManager.class);
SignedPreKeyEntity currentSignedPreKeyEntity = mock(SignedPreKeyEntity.class);
when(currentSignedPreKeyEntity.getKeyId()).thenReturn(3133);
when(accountManager.getSignedPreKey()).thenReturn(currentSignedPreKeyEntity);
final SignedPreKeyRecord currentRecord = new SignedPreKeyRecord(3133, System.currentTimeMillis(), Curve.generateKeyPair(), new byte[64]);
List<SignedPreKeyRecord> records = new LinkedList<SignedPreKeyRecord>() {{
add(currentRecord);
}};
when(signedPreKeyStore.loadSignedPreKeys()).thenReturn(records);
when(signedPreKeyStore.loadSignedPreKey(eq(3133))).thenReturn(currentRecord);
CleanPreKeysJob cleanPreKeysJob = new CleanPreKeysJob(getContext());
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(accountManager, signedPreKeyStore));
objectGraph.inject(cleanPreKeysJob);
verify(signedPreKeyStore, never()).removeSignedPreKey(anyInt());
}
public void testConnectionError() throws Exception {
SignedPreKeyStore signedPreKeyStore = mock(SignedPreKeyStore.class);
TextSecureAccountManager accountManager = mock(TextSecureAccountManager.class);
MasterSecret masterSecret = mock(MasterSecret.class);
when(accountManager.getSignedPreKey()).thenThrow(new PushNetworkException("Connectivity error!"));
CleanPreKeysJob cleanPreKeysJob = new CleanPreKeysJob(getContext());
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(accountManager, signedPreKeyStore));
objectGraph.inject(cleanPreKeysJob);
try {
cleanPreKeysJob.onRun(masterSecret);
throw new AssertionError("should have failed!");
} catch (IOException e) {
assertTrue(cleanPreKeysJob.onShouldRetry(e));
}
}
@Module(injects = {CleanPreKeysJob.class})
public static class TestModule {
private final TextSecureAccountManager accountManager;
private final SignedPreKeyStore signedPreKeyStore;
private TestModule(TextSecureAccountManager accountManager, SignedPreKeyStore signedPreKeyStore) {
this.accountManager = accountManager;
this.signedPreKeyStore = signedPreKeyStore;
}
@Provides TextSecureAccountManager provideTextSecureAccountManager() {
return accountManager;
}
@Provides
AxolotlStorageModule.SignedPreKeyStoreFactory provideSignedPreKeyStore() {
return new AxolotlStorageModule.SignedPreKeyStoreFactory() {
@Override
public SignedPreKeyStore create(MasterSecret masterSecret) {
return signedPreKeyStore;
}
};
}
}
}

View File

@@ -0,0 +1,101 @@
package org.thoughtcrime.securesms.jobs;
import android.test.AndroidTestCase;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.whispersystems.textsecure.api.TextSecureMessageSender;
import org.whispersystems.textsecure.api.push.PushAddress;
import org.whispersystems.textsecure.api.push.exceptions.NotFoundException;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
import java.io.IOException;
import dagger.Module;
import dagger.ObjectGraph;
import dagger.Provides;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.thoughtcrime.securesms.dependencies.TextSecureCommunicationModule.TextSecureMessageSenderFactory;
public class DeliveryReceiptJobTest extends AndroidTestCase {
public void testDelivery() throws IOException {
TextSecureMessageSender textSecureMessageSender = mock(TextSecureMessageSender.class);
long timestamp = System.currentTimeMillis();
DeliveryReceiptJob deliveryReceiptJob = new DeliveryReceiptJob(getContext(),
"+14152222222",
timestamp, "foo");
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(textSecureMessageSender));
objectGraph.inject(deliveryReceiptJob);
deliveryReceiptJob.onRun();
ArgumentCaptor<PushAddress> captor = ArgumentCaptor.forClass(PushAddress.class);
verify(textSecureMessageSender).sendDeliveryReceipt(captor.capture(), eq(timestamp));
assertTrue(captor.getValue().getRelay().equals("foo"));
assertTrue(captor.getValue().getNumber().equals("+14152222222"));
}
public void testNetworkError() throws IOException {
TextSecureMessageSender textSecureMessageSender = mock(TextSecureMessageSender.class);
long timestamp = System.currentTimeMillis();
Mockito.doThrow(new PushNetworkException("network error"))
.when(textSecureMessageSender)
.sendDeliveryReceipt(any(PushAddress.class), eq(timestamp));
DeliveryReceiptJob deliveryReceiptJob = new DeliveryReceiptJob(getContext(),
"+14152222222",
timestamp, "foo");
ObjectGraph objectGraph = ObjectGraph.create(new TestModule(textSecureMessageSender));
objectGraph.inject(deliveryReceiptJob);
try {
deliveryReceiptJob.onRun();
throw new AssertionError();
} catch (IOException e) {
assertTrue(deliveryReceiptJob.onShouldRetry(e));
}
Mockito.doThrow(new NotFoundException("not found"))
.when(textSecureMessageSender)
.sendDeliveryReceipt(any(PushAddress.class), eq(timestamp));
try {
deliveryReceiptJob.onRun();
throw new AssertionError();
} catch (IOException e) {
assertFalse(deliveryReceiptJob.onShouldRetry(e));
}
}
@Module(injects = DeliveryReceiptJob.class)
public static class TestModule {
private final TextSecureMessageSender textSecureMessageSender;
public TestModule(TextSecureMessageSender textSecureMessageSender) {
this.textSecureMessageSender = textSecureMessageSender;
}
@Provides TextSecureMessageSenderFactory provideTextSecureMessageSenderFactory() {
return new TextSecureMessageSenderFactory() {
@Override
public TextSecureMessageSender create(MasterSecret masterSecret) {
return textSecureMessageSender;
}
};
}
}
}

View File

@@ -0,0 +1,33 @@
package org.thoughtcrime.securesms.util;
import android.test.AndroidTestCase;
import junit.framework.AssertionFailedError;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
import static org.fest.assertions.api.Assertions.assertThat;
public class PhoneNumberFormatterTest extends AndroidTestCase {
private static final String LOCAL_NUMBER = "+15555555555";
public void testFormatNumberE164() throws Exception, InvalidNumberException {
assertThat(PhoneNumberFormatter.formatNumber("(555) 555-5555", LOCAL_NUMBER)).isEqualTo(LOCAL_NUMBER);
assertThat(PhoneNumberFormatter.formatNumber("555-5555", LOCAL_NUMBER)).isEqualTo(LOCAL_NUMBER);
assertThat(PhoneNumberFormatter.formatNumber("(123) 555-5555", LOCAL_NUMBER)).isNotEqualTo(LOCAL_NUMBER);
}
public void testFormatNumberEmail() throws Exception {
try {
PhoneNumberFormatter.formatNumber("person@domain.com", LOCAL_NUMBER);
throw new AssertionFailedError("should have thrown on email");
} catch (InvalidNumberException ine) {
// success
}
}
@Override
public void setUp() throws Exception {
super.setUp();
}
}

View File

@@ -0,0 +1,9 @@
package org.thoughtcrime.securesms.util;
import android.test.AndroidTestCase;
import static org.fest.assertions.api.Assertions.assertThat;
public class UtilTest extends AndroidTestCase {
}

View File

@@ -0,0 +1,28 @@
package org.thoughtcrime.securesms.service;
import android.content.Intent;
import android.test.InstrumentationTestCase;
import static org.fest.assertions.api.Assertions.*;
public class MmsReceiverTest extends InstrumentationTestCase {
private MmsReceiver mmsReceiver;
public void setUp() throws Exception {
super.setUp();
mmsReceiver = new MmsReceiver(getInstrumentation().getContext());
}
public void tearDown() throws Exception {
}
public void testProcessMalformedData() throws Exception {
Intent intent = new Intent();
intent.setAction(SendReceiveService.RECEIVE_MMS_ACTION);
intent.putExtra("data", new byte[]{0x00});
mmsReceiver.process(null, intent);
}
}

2
apntool/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.db
*.db.gz

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

81
apntool/apntool.py Normal file
View File

@@ -0,0 +1,81 @@
import sys
import argparse
import sqlite3
import gzip
from progressbar import ProgressBar, Counter, Timer
from lxml import etree
parser = argparse.ArgumentParser(prog='apntool', description="""Process Android's apn xml files and drop them into an easily
queryable SQLite db. Tested up to version 9 of their APN file.""")
parser.add_argument('-v', '--version', action='version', version='%(prog)s v1.0')
parser.add_argument('-i', '--input', help='the xml file to parse', default='apns.xml', required=False)
parser.add_argument('-o', '--output', help='the sqlite db output file', default='apns.db', required=False)
parser.add_argument('--quiet', help='do not show progress or verbose instructions', action='store_true', required=False)
parser.add_argument('--no-gzip', help="do not gzip after creation", action='store_true', required=False)
args = parser.parse_args()
try:
connection = sqlite3.connect(args.output)
cursor = connection.cursor()
cursor.execute('SELECT SQLITE_VERSION()')
version = cursor.fetchone()
if not args.quiet:
print("SQLite version: %s" % version)
print("Opening %s" % args.input)
cursor.execute("PRAGMA legacy_file_format=ON")
cursor.execute("PRAGMA journal_mode=DELETE")
cursor.execute("PRAGMA page_size=32768")
cursor.execute("VACUUM")
cursor.execute("DROP TABLE IF EXISTS apns")
cursor.execute("""CREATE TABLE apns(_id INTEGER PRIMARY KEY, mccmnc TEXT, mcc TEXT, mnc TEXT, carrier TEXT, apn TEXT,
mmsc TEXT, port INTEGER, type TEXT, protocol TEXT, bearer TEXT, roaming_protocol TEXT,
carrier_enabled INTEGER, mmsproxy TEXT, mmsport INTEGER, proxy TEXT, mvno_match_data TEXT,
mvno_type TEXT, authtype INTEGER, user TEXT, password TEXT, server TEXT)""")
apns = etree.parse(args.input)
root = apns.getroot()
pbar = ProgressBar(widgets=['Processed: ', Counter(), ' apns (', Timer(), ')'], maxval=len(list(root))).start() if not args.quiet else None
count = 0
for apn in root.iter("apn"):
if apn.get("mmsc") == None:
continue
sqlvars = ["?" for x in apn.attrib.keys()] + ["?"]
mccmnc = "%s%s" % (apn.get("mcc"), apn.get("mnc"))
values = [apn.get(attrib) for attrib in apn.attrib.keys()] + [mccmnc]
keys = apn.attrib.keys() + ["mccmnc"]
cursor.execute("SELECT 1 FROM apns WHERE mccmnc = ? AND apn = ?", [mccmnc, apn.get("apn")])
if cursor.fetchone() == None:
statement = "INSERT INTO apns (%s) VALUES (%s)" % (", ".join(keys), ", ".join(sqlvars))
cursor.execute(statement, values)
count += 1
if not args.quiet:
pbar.update(count)
if not args.quiet:
pbar.finish()
connection.commit()
print("Successfully written to %s" % args.output)
if not args.no_gzip:
gzipped_file = "%s.gz" % (args.output,)
with open(args.output, 'rb') as orig:
with gzip.open(gzipped_file, 'wb') as gzipped:
gzipped.writelines(orig)
print("Successfully gzipped to %s" % gzipped_file)
if not args.quiet:
print("\nTo include this in the distribution, copy it to the project's assets/databases/ directory.")
print("If you support API 10 or lower, you must use the gzipped version to avoid corruption.")
except sqlite3.Error, e:
if connection:
connection.rollback()
print("Error: %s" % e.args[0])
sys.exit(1)
finally:
if connection:
connection.close()

3
apntool/requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
argparse>=1.2.1
lxml>=3.3.3
progressbar-latest>=2.4

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 KiB

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 93 KiB

BIN
assets/databases/apns.db Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

BIN
assets/emoji_0_wrapped.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

BIN
assets/emoji_1_wrapped.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

BIN
assets/emoji_2_wrapped.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

BIN
assets/emoji_3_wrapped.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

BIN
assets/emoji_4_wrapped.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

View File

@@ -1,43 +1,109 @@
buildscript {
repositories {
mavenCentral()
maven {
url "https://repo1.maven.org/maven2"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
classpath 'com.android.tools.build:gradle:0.14.2'
classpath files('libs/gradle-witness.jar')
}
}
apply plugin: 'android'
apply plugin: 'com.android.application'
apply from: 'strip_play_services.gradle'
apply plugin: 'witness'
repositories {
mavenCentral()
maven {
url "https://raw.github.com/whispersystems/maven/master/gcm-client/releases/"
url "https://repo1.maven.org/maven2"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/preferencefragment/releases/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/gson/releases/"
}
maven {
url "https://raw.github.com/whispersystems/maven/master/smil/releases/"
}
}
dependencies {
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
compile 'com.android.support:support-v4:19.0.1'
compile 'com.google.android.gcm:gcm-client:1.0.2'
compile 'se.emilsjolander:stickylistheaders:2.2.0'
compile 'com.google.android.gms:play-services:6.1.71'
compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
compile 'org.w3c:smil:1.0.0'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.google.zxing:android-integration:3.1.0'
compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){
exclude module: 'support-v4'
}
compile 'com.squareup.dagger:dagger:1.2.2'
provided 'com.squareup.dagger:dagger-compiler:1.2.2'
compile project(':library')
compile 'org.whispersystems:jobmanager:0.9.0'
compile 'org.whispersystems:libpastelog:1.0.2'
androidTestCompile 'com.squareup:fest-android:1.0.8'
androidTestCompile 'com.google.dexmaker:dexmaker:1.1'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.1'
compile project(':libtextsecure')
}
dependencyVerification {
verify = [
'se.emilsjolander:stickylistheaders:89146b46c96fea0e40200474a2625cda10fe94891e4128f53cdb42375091b9b6',
'com.google.android.gms:play-services:32e7d1834a1cf8fa4b17e8d359db580c286e26c1eefbf84fdb9996eac8d74919',
'com.astuetz:pagerslidingtabstrip:f1641396732c7132a7abb837e482e5ee2b0ebb8d10813fc52bbaec2c15c184c2',
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad',
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
'com.android.support:support-v4:81f2b1c2c94efd5a4ec7fcd97b6cdcd00e87a933905c5c86103c7319eb024572',
'com.madgag.spongycastle:core:8d6240b974b0aca4d3da9c7dd44d42339d8a374358aca5fc98e50a995764511f',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'org.whispersystems:libpastelog:9798b3c93a91082c2c68542ce5b5c182e18556aebdcb7c8cebbd89eb48ac4047',
'com.google.protobuf:protobuf-java:e0c1c64575c005601725e7c6a02cebf9e1285e888f756b2a1d73ffa8d725cc74',
'com.googlecode.libphonenumber:libphonenumber:eba17eae81dd622ea89a00a3a8c025b2f25d342e0d9644c5b62e16f15687c3ab',
'org.whispersystems:gson:08f4f7498455d1539c9233e5aac18e9b1805815ef29221572996508eb512fe51',
'org.whispersystems:jobmanager:adb4329b69035053a7b6a48e22a3280235ac405b225ed8679b994612a8e6f5b6',
'com.android.support:support-annotations:1aa96ef0cc4a445bfc2f93ccf762305bc57fa107b12afe9d11f3863ae8a11036',
]
}
android {
compileSdkVersion 19
buildToolsVersion '19.0.2'
compileSdkVersion 21
buildToolsVersion '21.1.1'
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
buildTypes {
debug {
minifyEnabled false
}
release {
minifyEnabled false
}
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
@@ -48,6 +114,12 @@ android {
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
java.srcDirs = ['androidTest/java']
resources.srcDirs = ['androidTest/java']
aidl.srcDirs = ['androidTest/java']
renderscript.srcDirs = ['androidTest/java']
}
}
}
@@ -65,6 +137,12 @@ android {
}
}
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}
def Properties props = new Properties()
def propFile = new File('signing.properties')

View File

@@ -1,3 +1,30 @@
##Translations
Please do not submit issues or pull requests for translation fixes. Anyone can update the translations in [Transifex](https://www.transifex.com/projects/p/textsecure-official/). Please submit your corrections there.
## Submitting useful bug reports
1. Search our issues first to make sure this is not a duplicate.
1. Read the [Submitting useful bug reports guide](https://github.com/WhisperSystems/TextSecure/wiki/Submitting-useful-bug-reports) before posting a bug.
## Development Ideology
Truths which we believe to be self-evident:
1. **The answer is not more options.** If you feel compelled to add a
preference that's exposed to the user, it's very possible you've made
a wrong turn somewhere.
1. **The user doesn't know what a key is.** We need to minimize the points
at which a user is exposed to this sort of terminology as extremely as
possible.
1. **There are no power users.** The idea that some users "understand"
concepts better than others has proven to be, for the most part, false.
If anything, "power users" are more dangerous than the rest, and we
should avoid exposing dangerous functionality to them.
1. **If it's "like PGP," it's wrong.** PGP is our spirit guide for what
not to do.
1. **It's an asynchronous world.** Be wary of anything that is
anti-asynchronous: ACKs, protocol confirmations, or any protocol-level
"advisory" message.
1. **There is no such thing as time.** Protocol ideas that require synchronized
clocks are doomed to failure.

View File

@@ -1,6 +1,6 @@
#Mon Mar 10 23:44:05 PDT 2014
#Fri Nov 28 10:03:17 PST 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

2
libaxolotl/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/build
/obj

85
libaxolotl/README.md Normal file
View File

@@ -0,0 +1,85 @@
# Overview
This is a ratcheting forward secrecy protocol that works in synchronous and asynchronous messaging
environments. The protocol overview is available [here](https://github.com/trevp/axolotl/wiki),
and the details of the wire format are available [here](https://github.com/WhisperSystems/TextSecure/wiki/ProtocolV2).
## PreKeys
This protocol uses a concept called 'PreKeys'. A PreKey is an ECPublicKey and an associated unique
ID which are stored together by a server. PreKeys can also be signed.
At install time, clients generate a single signed PreKey, as well as a large list of unsigned
PreKeys, and transmit all of them to the server.
## Sessions
The axolotl protocol is session-oriented. Clients establish a "session," which is then used for
all subsequent encrypt/decrypt operations. There is no need to ever tear down a session once one
has been established.
Sessions are established in one of three ways:
1. PreKeyBundles. A client that wishes to send a message to a recipient can establish a session by
retrieving a PreKeyBundle for that recipient from the server.
1. PreKeyWhisperMessages. A client can receive a PreKeyWhisperMessage from a recipient and use it
to establish a session.
1. KeyExchangeMessages. Two clients can exchange KeyExchange messages to establish a session.
## State
An established session encapsulates a lot of state between two clients. That state is maintained
in durable records which need to be kept for the life of the session.
State is kept in the following places:
1. Identity State. Clients will need to maintain the state of their own identity key pair, as well
as identity keys received from other clients.
1. PreKey State. Clients will need to maintain the state of their generated PreKeys.
1. Signed PreKey States. Clients will need to maintain the state of their signed PreKeys.
1. Session State. Clients will need to maintain the state of the sessions they have established.
# Using libaxolotl
## Install time
At install time, a libaxolotl client needs to generate its identity keys, registration id, and
prekeys.
IdentityKeyPair identityKeyPair = KeyHelper.generateIdentityKeyPair();
int registrationId = KeyHelper.generateRegistrationId();
List<PreKeyRecord> preKeys = KeyHelper.generatePreKeys(startId, 100);
PreKeyRecord lastResortKey = KeyHelper.generateLastResortKey();
SignedPreKeyRecord 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:
SessionStore sessionStore = new MySessionStore();
PreKeyStore preKeyStore = new MyPreKeyStore();
SignedPreKeyStore signedPreKeyStore = new MySignedPreKeyStore();
IdentityKeyStore identityStore = new MyIdentityKeyStore();
// Instantiate a SessionBuilder for a remote recipientId + deviceId tuple.
SessionBuilder sessionBuilder = new SessionBuilder(sessionStore, preKeyStore, signedPreKeyStore,
identityStore, recipientId, deviceId);
// Build a session with a PreKey retrieved from the server.
sessionBuilder.process(retrievedPreKey);
SessionCipher sessionCipher = new SessionCipher(sessionStore, recipientId, deviceId);
CiphertextMessage message = sessionCipher.encrypt("Hello world!".getBytes("UTF-8"));
deliver(message.serialize());

44
libaxolotl/build.gradle Normal file
View File

@@ -0,0 +1,44 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.14.2'
}
}
apply plugin: 'com.android.library'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.protobuf:protobuf-java:2.5.0'
}
android {
compileSdkVersion 21
buildToolsVersion '21.1.1'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
}
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}

27
libaxolotl/jni/Android.mk Normal file
View File

@@ -0,0 +1,27 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519-donna
LOCAL_SRC_FILES := curve25519-donna.c
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519-ref10
LOCAL_SRC_FILES := $(wildcard ed25519/*.c) $(wildcard ed25519/additions/*.c) $(wildcard ed25519/nacl_sha512/*.c)
LOCAL_C_INCLUDES := ed25519/nacl_includes ed25519/additions ed25519/sha512 ed25519
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcurve25519
LOCAL_SRC_FILES := curve25519-jni.c
LOCAL_C_INCLUDES := ed25519/additions
LOCAL_STATIC_LIBRARIES := libcurve25519-donna libcurve25519-ref10
include $(BUILD_SHARED_LIBRARY)

View File

@@ -0,0 +1 @@
APP_ABI := armeabi armeabi-v7a x86 mips

View File

@@ -43,8 +43,7 @@
*
* This is, almost, a clean room reimplementation from the curve25519 paper. It
* uses many of the tricks described therein. Only the crecip function is taken
* from the sample implementation.
*/
* from the sample implementation. */
#include <string.h>
#include <stdint.h>
@@ -63,25 +62,23 @@ typedef int64_t limb;
* significant first. The value of the field element is:
* x[0] + 2^26·x[1] + x^51·x[2] + 2^102·x[3] + ...
*
* i.e. the limbs are 26, 25, 26, 25, ... bits wide.
*/
* i.e. the limbs are 26, 25, 26, 25, ... bits wide. */
/* Sum two numbers: output += in */
static void fsum(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; i += 2) {
output[0+i] = (output[0+i] + in[0+i]);
output[1+i] = (output[1+i] + in[1+i]);
output[0+i] = output[0+i] + in[0+i];
output[1+i] = output[1+i] + in[1+i];
}
}
/* Find the difference of two numbers: output = in - output
* (note the order of the arguments!)
*/
* (note the order of the arguments!). */
static void fdifference(limb *output, const limb *in) {
unsigned i;
for (i = 0; i < 10; ++i) {
output[i] = (in[i] - output[i]);
output[i] = in[i] - output[i];
}
}
@@ -97,7 +94,8 @@ static void fscalar_product(limb *output, const limb *in, const limb scalar) {
*
* output must be distinct to both inputs. The inputs are reduced coefficient
* form, the output is not.
*/
*
* output[x] <= 14 * the largest product of the input limbs. */
static void fproduct(limb *output, const limb *in2, const limb *in) {
output[0] = ((limb) ((s32) in2[0])) * ((s32) in[0]);
output[1] = ((limb) ((s32) in2[0])) * ((s32) in[1]) +
@@ -201,9 +199,15 @@ static void fproduct(limb *output, const limb *in2, const limb *in) {
output[18] = 2 * ((limb) ((s32) in2[9])) * ((s32) in[9]);
}
/* Reduce a long form to a short form by taking the input mod 2^255 - 19. */
/* Reduce a long form to a short form by taking the input mod 2^255 - 19.
*
* On entry: |output[i]| < 14*2^54
* On exit: |output[0..8]| < 280*2^54 */
static void freduce_degree(limb *output) {
/* Each of these shifts and adds ends up multiplying the value by 19. */
/* Each of these shifts and adds ends up multiplying the value by 19.
*
* For output[0..8], the absolute entry value is < 14*2^54 and we add, at
* most, 19*14*2^54 thus, on exit, |output[0..8]| < 280*2^54. */
output[8] += output[18] << 4;
output[8] += output[18] << 1;
output[8] += output[18];
@@ -237,11 +241,13 @@ static void freduce_degree(limb *output) {
#error "This code only works on a two's complement system"
#endif
/* return v / 2^26, using only shifts and adds. */
/* return v / 2^26, using only shifts and adds.
*
* On entry: v can take any value. */
static inline limb
div_by_2_26(const limb v)
{
/* High word of v; no shift needed*/
/* High word of v; no shift needed. */
const uint32_t highword = (uint32_t) (((uint64_t) v) >> 32);
/* Set to all 1s if v was negative; else set to 0s. */
const int32_t sign = ((int32_t) highword) >> 31;
@@ -251,7 +257,9 @@ div_by_2_26(const limb v)
return (v + roundoff) >> 26;
}
/* return v / (2^25), using only shifts and adds. */
/* return v / (2^25), using only shifts and adds.
*
* On entry: v can take any value. */
static inline limb
div_by_2_25(const limb v)
{
@@ -265,6 +273,9 @@ div_by_2_25(const limb v)
return (v + roundoff) >> 25;
}
/* return v / (2^25), using only shifts and adds.
*
* On entry: v can take any value. */
static inline s32
div_s32_by_2_25(const s32 v)
{
@@ -274,8 +285,7 @@ div_s32_by_2_25(const s32 v)
/* Reduce all coefficients of the short form input so that |x| < 2^26.
*
* On entry: |output[i]| < 2^62
*/
* On entry: |output[i]| < 280*2^54 */
static void freduce_coefficients(limb *output) {
unsigned i;
@@ -283,56 +293,65 @@ static void freduce_coefficients(limb *output) {
for (i = 0; i < 10; i += 2) {
limb over = div_by_2_26(output[i]);
/* The entry condition (that |output[i]| < 280*2^54) means that over is, at
* most, 280*2^28 in the first iteration of this loop. This is added to the
* next limb and we can approximate the resulting bound of that limb by
* 281*2^54. */
output[i] -= over << 26;
output[i+1] += over;
/* For the first iteration, |output[i+1]| < 281*2^54, thus |over| <
* 281*2^29. When this is added to the next limb, the resulting bound can
* be approximated as 281*2^54.
*
* For subsequent iterations of the loop, 281*2^54 remains a conservative
* bound and no overflow occurs. */
over = div_by_2_25(output[i+1]);
output[i+1] -= over << 25;
output[i+2] += over;
}
/* Now |output[10]| < 2 ^ 38 and all other coefficients are reduced. */
/* Now |output[10]| < 281*2^29 and all other coefficients are reduced. */
output[0] += output[10] << 4;
output[0] += output[10] << 1;
output[0] += output[10];
output[10] = 0;
/* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19 * 2^38
* So |over| will be no more than 77825 */
/* Now output[1..9] are reduced, and |output[0]| < 2^26 + 19*281*2^29
* So |over| will be no more than 2^16. */
{
limb over = div_by_2_26(output[0]);
output[0] -= over << 26;
output[1] += over;
}
/* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 77825
* So |over| will be no more than 1. */
{
/* output[1] fits in 32 bits, so we can use div_s32_by_2_25 here. */
s32 over32 = div_s32_by_2_25((s32) output[1]);
output[1] -= over32 << 25;
output[2] += over32;
}
/* Finally, output[0,1,3..9] are reduced, and output[2] is "nearly reduced":
* we have |output[2]| <= 2^26. This is good enough for all of our math,
* but it will require an extra freduce_coefficients before fcontract. */
/* Now output[0,2..9] are reduced, and |output[1]| < 2^25 + 2^16 < 2^26. The
* bound on |output[1]| is sufficient to meet our needs. */
}
/* A helpful wrapper around fproduct: output = in * in2.
*
* output must be distinct to both inputs. The output is reduced degree and
* reduced coefficient.
*/
* On entry: |in[i]| < 2^27 and |in2[i]| < 2^27.
*
* output must be distinct to both inputs. The output is reduced degree
* (indeed, one need only provide storage for 10 limbs) and |output[i]| < 2^26. */
static void
fmul(limb *output, const limb *in, const limb *in2) {
limb t[19];
fproduct(t, in, in2);
/* |t[i]| < 14*2^54 */
freduce_degree(t);
freduce_coefficients(t);
/* |t[i]| < 2^26 */
memcpy(output, t, sizeof(limb) * 10);
}
/* Square a number: output = in**2
*
* output must be distinct from the input. The inputs are reduced coefficient
* form, the output is not.
*
* output[x] <= 14 * the largest product of the input limbs. */
static void fsquare_inner(limb *output, const limb *in) {
output[0] = ((limb) ((s32) in[0])) * ((s32) in[0]);
output[1] = 2 * ((limb) ((s32) in[0])) * ((s32) in[1]);
@@ -391,12 +410,23 @@ static void fsquare_inner(limb *output, const limb *in) {
output[18] = 2 * ((limb) ((s32) in[9])) * ((s32) in[9]);
}
/* fsquare sets output = in^2.
*
* On entry: The |in| argument is in reduced coefficients form and |in[i]| <
* 2^27.
*
* On exit: The |output| argument is in reduced coefficients form (indeed, one
* need only provide storage for 10 limbs) and |out[i]| < 2^26. */
static void
fsquare(limb *output, const limb *in) {
limb t[19];
fsquare_inner(t, in);
/* |t[i]| < 14*2^54 because the largest product of two limbs will be <
* 2^(27+27) and fsquare_inner adds together, at most, 14 of those
* products. */
freduce_degree(t);
freduce_coefficients(t);
/* |t[i]| < 2^26 */
memcpy(output, t, sizeof(limb) * 10);
}
@@ -417,7 +447,7 @@ fexpand(limb *output, const u8 *input) {
F(6, 19, 1, 0x3ffffff);
F(7, 22, 3, 0x1ffffff);
F(8, 25, 4, 0x3ffffff);
F(9, 28, 6, 0x3ffffff);
F(9, 28, 6, 0x1ffffff);
#undef F
}
@@ -425,60 +455,143 @@ fexpand(limb *output, const u8 *input) {
#error "This code only works when >> does sign-extension on negative numbers"
#endif
/* s32_eq returns 0xffffffff iff a == b and zero otherwise. */
static s32 s32_eq(s32 a, s32 b) {
a = ~(a ^ b);
a &= a << 16;
a &= a << 8;
a &= a << 4;
a &= a << 2;
a &= a << 1;
return a >> 31;
}
/* s32_gte returns 0xffffffff if a >= b and zero otherwise, where a and b are
* both non-negative. */
static s32 s32_gte(s32 a, s32 b) {
a -= b;
/* a >= 0 iff a >= b. */
return ~(a >> 31);
}
/* Take a fully reduced polynomial form number and contract it into a
* little-endian, 32-byte array
*/
* little-endian, 32-byte array.
*
* On entry: |input_limbs[i]| < 2^26 */
static void
fcontract(u8 *output, limb *input) {
fcontract(u8 *output, limb *input_limbs) {
int i;
int j;
s32 input[10];
s32 mask;
/* |input_limbs[i]| < 2^26, so it's valid to convert to an s32. */
for (i = 0; i < 10; i++) {
input[i] = input_limbs[i];
}
for (j = 0; j < 2; ++j) {
for (i = 0; i < 9; ++i) {
if ((i & 1) == 1) {
/* This calculation is a time-invariant way to make input[i] positive
by borrowing from the next-larger limb.
*/
const s32 mask = (s32)(input[i]) >> 31;
const s32 carry = -(((s32)(input[i]) & mask) >> 25);
input[i] = (s32)(input[i]) + (carry << 25);
input[i+1] = (s32)(input[i+1]) - carry;
/* This calculation is a time-invariant way to make input[i]
* non-negative by borrowing from the next-larger limb. */
const s32 mask = input[i] >> 31;
const s32 carry = -((input[i] & mask) >> 25);
input[i] = input[i] + (carry << 25);
input[i+1] = input[i+1] - carry;
} else {
const s32 mask = (s32)(input[i]) >> 31;
const s32 carry = -(((s32)(input[i]) & mask) >> 26);
input[i] = (s32)(input[i]) + (carry << 26);
input[i+1] = (s32)(input[i+1]) - carry;
const s32 mask = input[i] >> 31;
const s32 carry = -((input[i] & mask) >> 26);
input[i] = input[i] + (carry << 26);
input[i+1] = input[i+1] - carry;
}
}
/* There's no greater limb for input[9] to borrow from, but we can multiply
* by 19 and borrow from input[0], which is valid mod 2^255-19. */
{
const s32 mask = (s32)(input[9]) >> 31;
const s32 carry = -(((s32)(input[9]) & mask) >> 25);
input[9] = (s32)(input[9]) + (carry << 25);
input[0] = (s32)(input[0]) - (carry * 19);
const s32 mask = input[9] >> 31;
const s32 carry = -((input[9] & mask) >> 25);
input[9] = input[9] + (carry << 25);
input[0] = input[0] - (carry * 19);
}
/* After the first iteration, input[1..9] are non-negative and fit within
* 25 or 26 bits, depending on position. However, input[0] may be
* negative. */
}
/* The first borrow-propagation pass above ended with every limb
except (possibly) input[0] non-negative.
Since each input limb except input[0] is decreased by at most 1
by a borrow-propagation pass, the second borrow-propagation pass
could only have wrapped around to decrease input[0] again if the
first pass left input[0] negative *and* input[1] through input[9]
were all zero. In that case, input[1] is now 2^25 - 1, and this
last borrow-propagation step will leave input[1] non-negative.
*/
If input[0] was negative after the first pass, then it was because of a
carry from input[9]. On entry, input[9] < 2^26 so the carry was, at most,
one, since (2**26-1) >> 25 = 1. Thus input[0] >= -19.
In the second pass, each limb is decreased by at most one. Thus the second
borrow-propagation pass could only have wrapped around to decrease
input[0] again if the first pass left input[0] negative *and* input[1]
through input[9] were all zero. In that case, input[1] is now 2^25 - 1,
and this last borrow-propagation step will leave input[1] non-negative. */
{
const s32 mask = (s32)(input[0]) >> 31;
const s32 carry = -(((s32)(input[0]) & mask) >> 26);
input[0] = (s32)(input[0]) + (carry << 26);
input[1] = (s32)(input[1]) - carry;
const s32 mask = input[0] >> 31;
const s32 carry = -((input[0] & mask) >> 26);
input[0] = input[0] + (carry << 26);
input[1] = input[1] - carry;
}
/* Both passes through the above loop, plus the last 0-to-1 step, are
necessary: if input[9] is -1 and input[0] through input[8] are 0,
negative values will remain in the array until the end.
*/
/* All input[i] are now non-negative. However, there might be values between
* 2^25 and 2^26 in a limb which is, nominally, 25 bits wide. */
for (j = 0; j < 2; j++) {
for (i = 0; i < 9; i++) {
if ((i & 1) == 1) {
const s32 carry = input[i] >> 25;
input[i] &= 0x1ffffff;
input[i+1] += carry;
} else {
const s32 carry = input[i] >> 26;
input[i] &= 0x3ffffff;
input[i+1] += carry;
}
}
{
const s32 carry = input[9] >> 25;
input[9] &= 0x1ffffff;
input[0] += 19*carry;
}
}
/* If the first carry-chain pass, just above, ended up with a carry from
* input[9], and that caused input[0] to be out-of-bounds, then input[0] was
* < 2^26 + 2*19, because the carry was, at most, two.
*
* If the second pass carried from input[9] again then input[0] is < 2*19 and
* the input[9] -> input[0] carry didn't push input[0] out of bounds. */
/* It still remains the case that input might be between 2^255-19 and 2^255.
* In this case, input[1..9] must take their maximum value and input[0] must
* be >= (2^255-19) & 0x3ffffff, which is 0x3ffffed. */
mask = s32_gte(input[0], 0x3ffffed);
for (i = 1; i < 10; i++) {
if ((i & 1) == 1) {
mask &= s32_eq(input[i], 0x1ffffff);
} else {
mask &= s32_eq(input[i], 0x3ffffff);
}
}
/* mask is either 0xffffffff (if input >= 2^255-19) and zero otherwise. Thus
* this conditionally subtracts 2^255-19. */
input[0] -= mask & 0x3ffffed;
for (i = 1; i < 10; i++) {
if ((i & 1) == 1) {
input[i] -= mask & 0x1ffffff;
} else {
input[i] -= mask & 0x3ffffff;
}
}
input[1] <<= 2;
input[2] <<= 3;
@@ -516,7 +629,9 @@ fcontract(u8 *output, limb *input) {
* x z: short form, destroyed
* xprime zprime: short form, destroyed
* qmqp: short form, preserved
*/
*
* On entry and exit, the absolute value of the limbs of all inputs and outputs
* are < 2^26. */
static void fmonty(limb *x2, limb *z2, /* output 2Q */
limb *x3, limb *z3, /* output Q + Q' */
limb *x, limb *z, /* input Q */
@@ -527,43 +642,69 @@ static void fmonty(limb *x2, limb *z2, /* output 2Q */
memcpy(origx, x, 10 * sizeof(limb));
fsum(x, z);
fdifference(z, origx); // does x - z
/* |x[i]| < 2^27 */
fdifference(z, origx); /* does x - z */
/* |z[i]| < 2^27 */
memcpy(origxprime, xprime, sizeof(limb) * 10);
fsum(xprime, zprime);
/* |xprime[i]| < 2^27 */
fdifference(zprime, origxprime);
/* |zprime[i]| < 2^27 */
fproduct(xxprime, xprime, z);
/* |xxprime[i]| < 14*2^54: the largest product of two limbs will be <
* 2^(27+27) and fproduct adds together, at most, 14 of those products.
* (Approximating that to 2^58 doesn't work out.) */
fproduct(zzprime, x, zprime);
/* |zzprime[i]| < 14*2^54 */
freduce_degree(xxprime);
freduce_coefficients(xxprime);
/* |xxprime[i]| < 2^26 */
freduce_degree(zzprime);
freduce_coefficients(zzprime);
/* |zzprime[i]| < 2^26 */
memcpy(origxprime, xxprime, sizeof(limb) * 10);
fsum(xxprime, zzprime);
/* |xxprime[i]| < 2^27 */
fdifference(zzprime, origxprime);
/* |zzprime[i]| < 2^27 */
fsquare(xxxprime, xxprime);
/* |xxxprime[i]| < 2^26 */
fsquare(zzzprime, zzprime);
/* |zzzprime[i]| < 2^26 */
fproduct(zzprime, zzzprime, qmqp);
/* |zzprime[i]| < 14*2^52 */
freduce_degree(zzprime);
freduce_coefficients(zzprime);
/* |zzprime[i]| < 2^26 */
memcpy(x3, xxxprime, sizeof(limb) * 10);
memcpy(z3, zzprime, sizeof(limb) * 10);
fsquare(xx, x);
/* |xx[i]| < 2^26 */
fsquare(zz, z);
/* |zz[i]| < 2^26 */
fproduct(x2, xx, zz);
/* |x2[i]| < 14*2^52 */
freduce_degree(x2);
freduce_coefficients(x2);
/* |x2[i]| < 2^26 */
fdifference(zz, xx); // does zz = xx - zz
/* |zz[i]| < 2^27 */
memset(zzz + 10, 0, sizeof(limb) * 9);
fscalar_product(zzz, zz, 121665);
/* |zzz[i]| < 2^(27+17) */
/* No need to call freduce_degree here:
fscalar_product doesn't increase the degree of its input. */
freduce_coefficients(zzz);
/* |zzz[i]| < 2^26 */
fsum(zzz, xx);
/* |zzz[i]| < 2^27 */
fproduct(z2, zz, zzz);
/* |z2[i]| < 14*2^(26+27) */
freduce_degree(z2);
freduce_coefficients(z2);
/* |z2|i| < 2^26 */
}
/* Conditionally swap two reduced-form limb arrays if 'iswap' is 1, but leave
@@ -574,8 +715,7 @@ static void fmonty(limb *x2, limb *z2, /* output 2Q */
* wrong results. Also, the two limb arrays must be in reduced-coefficient,
* reduced-degree form: the values in a[10..19] or b[10..19] aren't swapped,
* and all all values in a[0..9],b[0..9] must have magnitude less than
* INT32_MAX.
*/
* INT32_MAX. */
static void
swap_conditional(limb a[19], limb b[19], limb iswap) {
unsigned i;
@@ -592,8 +732,7 @@ swap_conditional(limb a[19], limb b[19], limb iswap) {
*
* resultx/resultz: the x coordinate of the resulting curve point (short form)
* n: a little endian, 32-byte number
* q: a point of the curve (short form)
*/
* q: a point of the curve (short form) */
static void
cmult(limb *resultx, limb *resultz, const u8 *n, const limb *q) {
limb a[19] = {0}, b[19] = {1}, c[19] = {1}, d[19] = {0};
@@ -711,8 +850,6 @@ crecip(limb *out, const limb *z) {
/* 2^255 - 21 */ fmul(out,t1,z11);
}
int curve25519_donna(u8 *, const u8 *, const u8 *);
int
curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
limb bp[10], x[10], z[11], zmone[10];
@@ -720,12 +857,14 @@ curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) {
int i;
for (i = 0; i < 32; ++i) e[i] = secret[i];
// e[0] &= 248;
// e[31] &= 127;
// e[31] |= 64;
fexpand(bp, basepoint);
cmult(x, z, e, bp);
crecip(zmone, z);
fmul(z, x, zmone);
freduce_coefficients(z);
fcontract(mypublic, z);
return 0;
}

View File

@@ -0,0 +1,109 @@
/**
* Copyright (C) 2013-2014 Open Whisper Systems
*
* 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/>.
*/
#include <string.h>
#include <stdint.h>
#include <jni.h>
#include "curve25519-donna.h"
#include "curve_sigs.h"
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePrivateKey
(JNIEnv *env, jclass clazz, jbyteArray random)
{
uint8_t* privateKey = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
privateKey[0] &= 248;
privateKey[31] &= 127;
privateKey[31] |= 64;
(*env)->ReleaseByteArrayElements(env, random, privateKey, 0);
return random;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_generatePublicKey
(JNIEnv *env, jclass clazz, jbyteArray privateKey)
{
static const uint8_t basepoint[32] = {9};
jbyteArray publicKey = (*env)->NewByteArray(env, 32);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
curve25519_donna(publicKeyBytes, privateKeyBytes, basepoint);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
return publicKey;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateAgreement
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey)
{
jbyteArray sharedKey = (*env)->NewByteArray(env, 32);
uint8_t* sharedKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, sharedKey, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
curve25519_donna(sharedKeyBytes, privateKeyBytes, publicKeyBytes);
(*env)->ReleaseByteArrayElements(env, sharedKey, sharedKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
return sharedKey;
}
JNIEXPORT jbyteArray JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_calculateSignature
(JNIEnv *env, jclass clazz, jbyteArray random, jbyteArray privateKey, jbyteArray message)
{
jbyteArray signature = (*env)->NewByteArray(env, 64);
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* randomBytes = (uint8_t*)(*env)->GetByteArrayElements(env, random, 0);
uint8_t* privateKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, privateKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
int result = curve25519_sign(signatureBytes, privateKeyBytes, messageBytes, messageLength, randomBytes);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, random, randomBytes, 0);
(*env)->ReleaseByteArrayElements(env, privateKey, privateKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
if (result == 0) return signature;
else (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/AssertionError"), "Signature failed!");
}
JNIEXPORT jboolean JNICALL Java_org_whispersystems_libaxolotl_ecc_Curve25519_verifySignature
(JNIEnv *env, jclass clazz, jbyteArray publicKey, jbyteArray message, jbyteArray signature)
{
uint8_t* signatureBytes = (uint8_t*)(*env)->GetByteArrayElements(env, signature, 0);
uint8_t* publicKeyBytes = (uint8_t*)(*env)->GetByteArrayElements(env, publicKey, 0);
uint8_t* messageBytes = (uint8_t*)(*env)->GetByteArrayElements(env, message, 0);
jsize messageLength = (*env)->GetArrayLength(env, message);
jboolean result = (curve25519_verify(signatureBytes, publicKeyBytes, messageBytes, messageLength) == 0);
(*env)->ReleaseByteArrayElements(env, signature, signatureBytes, 0);
(*env)->ReleaseByteArrayElements(env, publicKey, publicKeyBytes, 0);
(*env)->ReleaseByteArrayElements(env, message, messageBytes, 0);
return result;
}

View File

@@ -0,0 +1,44 @@
#include <string.h>
#include "compare.h"
/* Const-time comparison from SUPERCOP, but here it's only used for
signature verification, so doesn't need to be const-time. But
copied the nacl version anyways. */
int crypto_verify_32_ref(const unsigned char *x, const unsigned char *y)
{
unsigned int differentbits = 0;
#define F(i) differentbits |= x[i] ^ y[i];
F(0)
F(1)
F(2)
F(3)
F(4)
F(5)
F(6)
F(7)
F(8)
F(9)
F(10)
F(11)
F(12)
F(13)
F(14)
F(15)
F(16)
F(17)
F(18)
F(19)
F(20)
F(21)
F(22)
F(23)
F(24)
F(25)
F(26)
F(27)
F(28)
F(29)
F(30)
F(31)
return (1 & ((differentbits - 1) >> 8)) - 1;
}

View File

@@ -0,0 +1,6 @@
#ifndef __COMPARE_H__
#define __COMPARE_H__
int crypto_verify_32_ref(const unsigned char *b1, const unsigned char *b2);
#endif

Some files were not shown because too many files have changed in this diff Show More