The options parameter, which appears in a few places, is used to pass
* several pieces of information to the encoder. In the "higher level" methods such as
@@ -24,10 +24,10 @@ package org.whispersystems.util;
*
The constants defined in Base64 can be OR-ed together to combine options, so you
* might make a call like this:
v2.3.4 - Fixed bug when working with gzipped streams whereby flushing
- * the Base64.OutputStream closed the Base64 encoding (by padding with equals
+ * the Base64Tools.OutputStream closed the Base64 encoding (by padding with equals
* signs) too soon. Also added an option to suppress the automatic decoding
* of gzipped streams. Also added experimental support for specifying a
* class loader when using the
- * {@link #decodeToObject(java.lang.String, int, java.lang.ClassLoader)}
+ * {@link #decodeToObject(String, int, ClassLoader)}
* method.
*
v2.3.3 - Changed default char encoding to US-ASCII which reduces the internal Java
* footprint with its CharEncoders and so forth. Fixed some javadocs that were
@@ -85,10 +85,10 @@ package org.whispersystems.util;
* encoding/decoding from one file to the next. Also added these Base64 dialects:
*
*
Calling Base64Tools.setFormat(Base64Tools.BASE64_FORMAT.URLSAFE_FORMAT) generates
* URL and file name friendly format as described in Section 4 of RFC3548.
* http://www.faqs.org/rfcs/rfc3548.html
Calling Base64Tools.setFormat(Base64Tools.BASE64_FORMAT.ORDERED_FORMAT) generates
* URL and file name friendly format that preserves lexical ordering as described
* in http://www.faqs.org/qa/rfcc-1940.html
*
@@ -136,38 +136,38 @@ package org.whispersystems.util;
* @author rob@iharder.net
* @version 2.3.3
*/
-public class Base64
+class Base64Tools
{
-
-/* ******** P U B L I C F I E L D S ******** */
-
-
+
+/* ******** P U B L I C F I E L D S ******** */
+
+
/** No options specified. Value is zero. */
public final static int NO_OPTIONS = 0;
-
+
/** Specify encoding in first bit. Value is one. */
public final static int ENCODE = 1;
-
-
+
+
/** Specify decoding in first bit. Value is zero. */
public final static int DECODE = 0;
-
+
/** Specify that data should be gzip-compressed in second bit. Value is two. */
public final static int GZIP = 2;
/** Specify that gzipped data should not be automatically gunzipped. */
public final static int DONT_GUNZIP = 4;
-
-
+
+
/** Do break lines when encoding. Value is 8. */
public final static int DO_BREAK_LINES = 8;
-
- /**
+
+ /**
* Encode using Base64-like encoding that is URL- and Filename-safe as described
- * in Section 4 of RFC3548:
+ * in Section 4 of RFC3548:
* http://www.faqs.org/rfcs/rfc3548.html.
- * It is important to note that data encoded this way is not officially valid Base64,
+ * It is important to note that data encoded this way is not officially valid Base64,
* or at the very least should not be called Base64 without also specifying that is
* was encoded using the URL- and Filename-safe dialect.
*/
@@ -179,50 +179,50 @@ public class Base64
* http://www.faqs.org/qa/rfcc-1940.html.
*/
public final static int ORDERED = 32;
-
-
-/* ******** P R I V A T E F I E L D S ******** */
-
-
+
+
+/* ******** P R I V A T E F I E L D S ******** */
+
+
/** Maximum line length (76) of Base64 output. */
private final static int MAX_LINE_LENGTH = 76;
-
-
+
+
/** The equals sign (=) as a byte. */
private final static byte EQUALS_SIGN = (byte)'=';
-
-
+
+
/** The new line character (\n) as a byte. */
private final static byte NEW_LINE = (byte)'\n';
-
-
+
+
/** Preferred encoding. */
private final static String PREFERRED_ENCODING = "US-ASCII";
-
-
+
+
private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding
private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding
-
-
-/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
-
+
+
+/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */
+
/** The 64 valid Base64 values. */
/* Host platform me be something funny like EBCDIC, so we hardcode these values. */
private final static byte[] _STANDARD_ALPHABET = {
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
(byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
(byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
(byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
(byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/'
};
-
-
- /**
+
+
+ /**
* Translates a Base64 value to either its 6-bit reconstruction value
* or a negative number indicating some other meaning.
**/
@@ -259,30 +259,30 @@ public class Base64
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
-
-
+
+
/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */
-
+
/**
- * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
+ * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548:
* http://www.faqs.org/rfcs/rfc3548.html.
* Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash."
*/
private final static byte[] _URL_SAFE_ALPHABET = {
(byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
(byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
- (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+ (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
(byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
(byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
- (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+ (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z',
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5',
(byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_'
};
-
+
/**
- * Used in decoding URL- and Filename-safe dialects of Base64.
+ * Used in decoding URL- and Filename-safe dialects of Base64Tools.
*/
private final static byte[] _URL_SAFE_DECODABET = {
-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
@@ -345,9 +345,9 @@ public class Base64
(byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
(byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z'
};
-
+
/**
- * Used in decoding the "ordered" dialect of Base64.
+ * Used in decoding the "ordered" dialect of Base64Tools.
*/
private final static byte[] _ORDERED_DECODABET = {
-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8
@@ -387,7 +387,7 @@ public class Base64
-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 */
};
-
+
/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */
@@ -427,9 +427,9 @@ public class Base64
} // end getAlphabet
-
+
/** Defeats instantiation. */
- private Base64(){}
+ private Base64Tools(){}
@@ -564,7 +564,7 @@ public class Base64
while( raw.hasRemaining() ){
int rem = Math.min(3,raw.remaining());
raw.get(raw3,0,rem);
- Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS );
+ Base64Tools.encode3to4(enc4, raw3, rem, Base64Tools.NO_OPTIONS );
encoded.put(enc4);
} // end input remaining
}
@@ -588,7 +588,7 @@ public class Base64
while( raw.hasRemaining() ){
int rem = Math.min(3,raw.remaining());
raw.get(raw3,0,rem);
- Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS );
+ Base64Tools.encode3to4(enc4, raw3, rem, Base64Tools.NO_OPTIONS );
for( int i = 0; i < 4; i++ ){
encoded.put( (char)(enc4[i] & 0xFF) );
}
@@ -640,9 +640,9 @@ public class Base64
* DO_BREAK_LINES: break lines at 76 characters
*
*
- * Example: encodeObject( myObj, Base64.GZIP ) or
+ * Example: encodeObject( myObj, Base64Tools.GZIP ) or
*
- * Example: encodeObject( myObj, Base64.GZIP | Base64.DO_BREAK_LINES )
+ * Example: encodeObject( myObj, Base64Tools.GZIP | Base64Tools.DO_BREAK_LINES )
*
* @param serializableObject The object to encode
* @param options Specified options
@@ -669,7 +669,7 @@ public class Base64
try {
// ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | options );
+ b64os = new Base64Tools.OutputStream( baos, ENCODE | options );
if( (options & GZIP) != 0 ){
// Gzip
gzos = new java.util.zip.GZIPOutputStream(b64os);
@@ -760,9 +760,9 @@ public class Base64
* Note: Technically, this makes your encoding non-compliant.
*
*
- * Example: encodeBytes( myData, Base64.GZIP ) or
+ * Example: encodeBytes( myData, Base64Tools.GZIP ) or
*
As of v 2.3, if there is an error with the GZIP stream,
@@ -828,9 +828,9 @@ public class Base64
* Note: Technically, this makes your encoding non-compliant.
*
*
- * Example: encodeBytes( myData, Base64.GZIP ) or
+ * Example: encodeBytes( myData, Base64Tools.GZIP ) or
*
As of v 2.3, if there is an error with the GZIP stream,
@@ -881,7 +881,7 @@ public class Base64
public static byte[] encodeBytesToBytes( byte[] source ) {
byte[] encoded = null;
try {
- encoded = encodeBytesToBytes( source, 0, source.length, Base64.NO_OPTIONS );
+ encoded = encodeBytesToBytes( source, 0, source.length, Base64Tools.NO_OPTIONS );
} catch( java.io.IOException ex ) {
assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage();
}
@@ -932,12 +932,12 @@ public class Base64
if( (options & GZIP) != 0 ) {
java.io.ByteArrayOutputStream baos = null;
java.util.zip.GZIPOutputStream gzos = null;
- Base64.OutputStream b64os = null;
+ Base64Tools.OutputStream b64os = null;
try {
// GZip -> Base64 -> ByteArray
baos = new java.io.ByteArrayOutputStream();
- b64os = new Base64.OutputStream( baos, ENCODE | options );
+ b64os = new Base64Tools.OutputStream( baos, ENCODE | options );
gzos = new java.util.zip.GZIPOutputStream( b64os );
gzos.write( source, off, len );
@@ -1138,7 +1138,7 @@ public class Base64
public static byte[] decode( byte[] source ){
byte[] decoded = null;
try {
- decoded = decode( source, 0, source.length, Base64.NO_OPTIONS );
+ decoded = decode( source, 0, source.length, Base64Tools.NO_OPTIONS );
} catch( java.io.IOException ex ) {
assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage();
}
@@ -1345,7 +1345,7 @@ public class Base64
* @since 1.5
*/
public static Object decodeToObject( String encodedObject )
- throws java.io.IOException, java.lang.ClassNotFoundException {
+ throws java.io.IOException, ClassNotFoundException {
return decodeToObject(encodedObject,NO_OPTIONS,null);
}
@@ -1368,7 +1368,7 @@ public class Base64
*/
public static Object decodeToObject(
String encodedObject, int options, final ClassLoader loader )
- throws java.io.IOException, java.lang.ClassNotFoundException {
+ throws java.io.IOException, ClassNotFoundException {
// Decode and gunzip if necessary
byte[] objBytes = decode( encodedObject, options );
@@ -1407,7 +1407,7 @@ public class Base64
catch( java.io.IOException e ) {
throw e; // Catch and throw in order to execute finally{}
} // end catch
- catch( java.lang.ClassNotFoundException e ) {
+ catch( ClassNotFoundException e ) {
throw e; // Catch and throw in order to execute finally{}
} // end catch
finally {
@@ -1441,10 +1441,10 @@ public class Base64
throw new NullPointerException( "Data to encode was null." );
} // end iff
- Base64.OutputStream bos = null;
+ Base64Tools.OutputStream bos = null;
try {
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ), Base64.ENCODE );
+ bos = new Base64Tools.OutputStream(
+ new java.io.FileOutputStream( filename ), Base64Tools.ENCODE );
bos.write( dataToEncode );
} // end try
catch( java.io.IOException e ) {
@@ -1473,10 +1473,10 @@ public class Base64
public static void decodeToFile( String dataToDecode, String filename )
throws java.io.IOException {
- Base64.OutputStream bos = null;
+ Base64Tools.OutputStream bos = null;
try{
- bos = new Base64.OutputStream(
- new java.io.FileOutputStream( filename ), Base64.DECODE );
+ bos = new Base64Tools.OutputStream(
+ new java.io.FileOutputStream( filename ), Base64Tools.DECODE );
bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) );
} // end try
catch( java.io.IOException e ) {
@@ -1509,7 +1509,7 @@ public class Base64
throws java.io.IOException {
byte[] decodedData = null;
- Base64.InputStream bis = null;
+ Base64Tools.InputStream bis = null;
try
{
// Set up some useful variables
@@ -1526,9 +1526,9 @@ public class Base64
buffer = new byte[ (int)file.length() ];
// Open a stream
- bis = new Base64.InputStream(
+ bis = new Base64Tools.InputStream(
new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.DECODE );
+ new java.io.FileInputStream( file ) ), Base64Tools.DECODE );
// Read until done
while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) {
@@ -1570,7 +1570,7 @@ public class Base64
throws java.io.IOException {
String encodedData = null;
- Base64.InputStream bis = null;
+ Base64Tools.InputStream bis = null;
try
{
// Set up some useful variables
@@ -1580,9 +1580,9 @@ public class Base64
int numBytes = 0;
// Open a stream
- bis = new Base64.InputStream(
+ bis = new Base64Tools.InputStream(
new java.io.BufferedInputStream(
- new java.io.FileInputStream( file ) ), Base64.ENCODE );
+ new java.io.FileInputStream( file ) ), Base64Tools.ENCODE );
// Read until done
while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) {
@@ -1590,7 +1590,7 @@ public class Base64
} // end while
// Save in a variable to return
- encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING );
+ encodedData = new String( buffer, 0, length, Base64Tools.PREFERRED_ENCODING );
} // end try
catch( java.io.IOException e ) {
@@ -1614,7 +1614,7 @@ public class Base64
public static void encodeFileToFile( String infile, String outfile )
throws java.io.IOException {
- String encoded = Base64.encodeFromFile( infile );
+ String encoded = Base64Tools.encodeFromFile( infile );
java.io.OutputStream out = null;
try{
out = new java.io.BufferedOutputStream(
@@ -1642,7 +1642,7 @@ public class Base64
public static void decodeFileToFile( String infile, String outfile )
throws java.io.IOException {
- byte[] decoded = Base64.decodeFromFile( infile );
+ byte[] decoded = Base64Tools.decodeFromFile( infile );
java.io.OutputStream out = null;
try{
out = new java.io.BufferedOutputStream(
@@ -1664,7 +1664,7 @@ public class Base64
/**
- * A {@link Base64.InputStream} will read data from another
+ * A {@link Base64Tools.InputStream} will read data from another
* java.io.InputStream, given in the constructor,
* and encode/decode to/from Base64 notation on the fly.
*
@@ -1685,7 +1685,7 @@ public class Base64
/**
- * Constructs a {@link Base64.InputStream} in DECODE mode.
+ * Constructs a {@link Base64Tools.InputStream} in DECODE mode.
*
* @param in the java.io.InputStream from which to read data.
* @since 1.3
@@ -1696,7 +1696,7 @@ public class Base64
/**
- * Constructs a {@link Base64.InputStream} in
+ * Constructs a {@link Base64Tools.InputStream} in
* either ENCODE or DECODE mode.
*
* Valid options:
@@ -1705,7 +1705,7 @@ public class Base64
* (only meaningful when encoding)
*
*
- * Example: new Base64.InputStream( in, Base64.DECODE )
+ * Example: new Base64Tools.InputStream( in, Base64Tools.DECODE )
*
*
* @param in the java.io.InputStream from which to read data.
@@ -1877,7 +1877,7 @@ public class Base64
/**
- * A {@link Base64.OutputStream} will write data to another
+ * A {@link Base64Tools.OutputStream} will write data to another
* java.io.OutputStream, given in the constructor,
* and encode/decode to/from Base64 notation on the fly.
*
@@ -1898,7 +1898,7 @@ public class Base64
private byte[] decodabet; // Local copies to avoid extra method calls
/**
- * Constructs a {@link Base64.OutputStream} in ENCODE mode.
+ * Constructs a {@link Base64Tools.OutputStream} in ENCODE mode.
*
* @param out the java.io.OutputStream to which data will be written.
* @since 1.3
@@ -1909,7 +1909,7 @@ public class Base64
/**
- * Constructs a {@link Base64.OutputStream} in
+ * Constructs a {@link Base64Tools.OutputStream} in
* either ENCODE or DECODE mode.
*
* Valid options:
@@ -1918,7 +1918,7 @@ public class Base64
* (only meaningful when encoding)
*
*
- * Example: new Base64.OutputStream( out, Base64.ENCODE )
+ * Example: new Base64Tools.OutputStream( out, Base64Tools.ENCODE )
*
* @param out the java.io.OutputStream to which data will be written.
* @param options Specified options.
@@ -1987,7 +1987,7 @@ public class Base64
buffer[ position++ ] = (byte)theByte;
if( position >= bufferLength ) { // Enough to output.
- int len = Base64.decode4to3( buffer, 0, b4, 0, options );
+ int len = Base64Tools.decode4to3( buffer, 0, b4, 0, options );
out.write( b4, 0, len );
position = 0;
} // end if: enough to output
diff --git a/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt b/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt
new file mode 100644
index 0000000000..54a2507d0d
--- /dev/null
+++ b/core-util-jvm/src/test/java/org/signal/core/util/Base64Test.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.signal.core.util
+
+import org.junit.Assert.assertArrayEquals
+import org.junit.Test
+import kotlin.random.Random
+
+class Base64Test {
+
+ @Test
+ fun `decode - correctly decode all strings regardless of url safety or padding`() {
+ val stopwatch = Stopwatch("time", 2)
+
+ for (len in 0 until 256) {
+ for (i in 0..2_000) {
+ val bytes = Random.nextBytes(len)
+
+ val padded = Base64.encodeWithPadding(bytes)
+ val unpadded = Base64.encodeWithoutPadding(bytes)
+ val urlSafePadded = Base64.encodeUrlSafeWithPadding(bytes)
+ val urlSafeUnpadded = Base64.encodeUrlSafeWithoutPadding(bytes)
+
+ assertArrayEquals(bytes, Base64.decode(padded))
+ assertArrayEquals(bytes, Base64.decode(unpadded))
+ assertArrayEquals(bytes, Base64.decode(urlSafePadded))
+ assertArrayEquals(bytes, Base64.decode(urlSafeUnpadded))
+ }
+ }
+
+ println(stopwatch.stopAndGetLogString())
+ }
+}
diff --git a/libsignal-service/build.gradle b/libsignal-service/build.gradle
index eb476cdd0a..4e342943bc 100644
--- a/libsignal-service/build.gradle
+++ b/libsignal-service/build.gradle
@@ -65,6 +65,8 @@ dependencies {
implementation libs.kotlin.stdlib.jdk8
+ implementation project(":core-util-jvm")
+
testImplementation testLibs.junit.junit
testImplementation testLibs.assertj.core
testImplementation testLibs.conscrypt.openjdk.uber
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java
index c4ae426bf5..fbaf774da9 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java
@@ -81,8 +81,7 @@ import org.whispersystems.signalservice.internal.storage.protos.WriteOperation;
import org.whispersystems.signalservice.internal.util.StaticCredentialsProvider;
import org.whispersystems.signalservice.internal.util.Util;
import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper;
-import org.whispersystems.util.Base64;
-import org.whispersystems.util.Base64UrlSafe;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.security.KeyStore;
@@ -801,7 +800,7 @@ public class SignalServiceAccountManager {
public UsernameLinkComponents createUsernameLink(Username username) throws IOException {
try {
UsernameLink link = username.generateLink();
- UUID serverId = this.pushServiceSocket.createUsernameLink(Base64UrlSafe.encodeBytes(link.getEncryptedUsername()));
+ UUID serverId = this.pushServiceSocket.createUsernameLink(Base64.encodeUrlSafeWithPadding(link.getEncryptedUsername()));
return new UsernameLinkComponents(link.getEntropy(), serverId);
} catch (BaseUsernameException e) {
@@ -841,7 +840,7 @@ public class SignalServiceAccountManager {
try {
MessageDigest digest = MessageDigest.getInstance("SHA1");
byte[] token = Util.trim(digest.digest(e164number.getBytes()), 10);
- String encoded = Base64.encodeBytesWithoutPadding(token);
+ String encoded = Base64.encodeWithoutPadding(token);
if (urlSafe) return encoded.replace('+', '-').replace('/', '_');
else return encoded;
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java
index 6e0df4b0aa..7cd3a3a7c9 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java
@@ -127,7 +127,7 @@ import org.whispersystems.signalservice.internal.push.http.PartialSendBatchCompl
import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener;
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
import org.whispersystems.signalservice.internal.util.Util;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import org.whispersystems.util.ByteArrayUtil;
import java.io.IOException;
@@ -888,7 +888,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException
{
byte[] nullMessageBody = new DataMessage.Builder()
- .body(Base64.encodeBytes(Util.getRandomLengthBytes(140)))
+ .body(Base64.encodeWithPadding(Util.getRandomLengthBytes(140)))
.build()
.encode();
@@ -918,7 +918,7 @@ public class SignalServiceMessageSender {
throws UntrustedIdentityException, IOException
{
byte[] nullMessageBody = new DataMessage.Builder()
- .body(Base64.encodeBytes(Util.getRandomLengthBytes(140)))
+ .body(Base64.encodeWithPadding(Util.getRandomLengthBytes(140)))
.build()
.encode();
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java
index 0c7dccce8f..d326dfe99f 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalWebSocket.java
@@ -11,7 +11,7 @@ import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage;
import org.whispersystems.signalservice.internal.websocket.WebSocketResponseMessage;
import org.whispersystems.signalservice.internal.websocket.WebsocketResponse;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.util.ArrayList;
@@ -201,7 +201,7 @@ public final class SignalWebSocket {
public Single request(WebSocketRequestMessage requestMessage, Optional unidentifiedAccess) {
if (unidentifiedAccess.isPresent()) {
List headers = new ArrayList<>(requestMessage.headers);
- headers.add("Unidentified-Access-Key:" + Base64.encodeBytes(unidentifiedAccess.get().getUnidentifiedAccessKey()));
+ headers.add("Unidentified-Access-Key:" + Base64.encodeWithPadding(unidentifiedAccess.get().getUnidentifiedAccessKey()));
WebSocketRequestMessage message = requestMessage.newBuilder()
.headers(headers)
.build();
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java
index aeea9fb0a2..1d87bb3916 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/crypto/EnvelopeContent.java
@@ -13,7 +13,7 @@ import org.whispersystems.signalservice.internal.push.Content;
import org.whispersystems.signalservice.internal.push.Envelope.Type;
import org.whispersystems.signalservice.internal.push.OutgoingPushMessage;
import org.whispersystems.signalservice.internal.push.PushTransportDetails;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.util.Optional;
@@ -88,7 +88,7 @@ public interface EnvelopeContent {
groupId);
byte[] ciphertext = sealedSessionCipher.encrypt(destination, messageContent);
- String body = Base64.encodeBytes(ciphertext);
+ String body = Base64.encodeWithPadding(ciphertext);
int remoteRegistrationId = sealedSessionCipher.getRemoteRegistrationId(destination);
return new OutgoingPushMessage(Type.UNIDENTIFIED_SENDER.getValue(), destination.getDeviceId(), remoteRegistrationId, body);
@@ -99,7 +99,7 @@ public interface EnvelopeContent {
PushTransportDetails transportDetails = new PushTransportDetails();
CiphertextMessage message = sessionCipher.encrypt(transportDetails.getPaddedMessageBody(content.encode()));
int remoteRegistrationId = sessionCipher.getRemoteRegistrationId();
- String body = Base64.encodeBytes(message.serialize());
+ String body = Base64.encodeWithPadding(message.serialize());
int type;
@@ -146,7 +146,7 @@ public interface EnvelopeContent {
groupId);
byte[] ciphertext = sealedSessionCipher.encrypt(destination, messageContent);
- String body = Base64.encodeBytes(ciphertext);
+ String body = Base64.encodeWithPadding(ciphertext);
int remoteRegistrationId = sealedSessionCipher.getRemoteRegistrationId(destination);
return new OutgoingPushMessage(Type.UNIDENTIFIED_SENDER.getValue(), destination.getDeviceId(), remoteRegistrationId, body);
@@ -154,7 +154,7 @@ public interface EnvelopeContent {
@Override
public OutgoingPushMessage processUnsealedSender(SignalSessionCipher sessionCipher, SignalProtocolAddress destination) {
- String body = Base64.encodeBytes(plaintextContent.serialize());
+ String body = Base64.encodeWithPadding(plaintextContent.serialize());
int remoteRegistrationId = sessionCipher.getRemoteRegistrationId();
return new OutgoingPushMessage(Type.PLAINTEXT_CONTENT.getValue(), destination.getDeviceId(), remoteRegistrationId, body);
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java
index 5e6f43354b..c4708c7b23 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/kbs/MasterKey.java
@@ -2,7 +2,7 @@ package org.whispersystems.signalservice.api.kbs;
import org.whispersystems.signalservice.api.storage.StorageKey;
import org.whispersystems.signalservice.internal.util.Hex;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import org.whispersystems.util.StringUtil;
import java.security.SecureRandom;
@@ -33,7 +33,7 @@ public final class MasterKey {
}
public String deriveRegistrationRecoveryPassword() {
- return Base64.encodeBytes(derive("Registration Recovery"));
+ return Base64.encodeWithPadding(derive("Registration Recovery"));
}
public StorageKey deriveStorageServiceKey() {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java
index f5b108f118..2ae05785e3 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/push/SignedPreKeyEntity.java
@@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
import org.whispersystems.signalservice.internal.push.PreKeyEntity;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
@@ -43,7 +43,7 @@ public class SignedPreKeyEntity extends PreKeyEntity {
private static class ByteArraySerializer extends JsonSerializer {
@Override
public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytesWithoutPadding(value));
+ gen.writeString(Base64.encodeWithoutPadding(value));
}
}
@@ -51,7 +51,7 @@ public class SignedPreKeyEntity extends PreKeyEntity {
@Override
public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
- return Base64.decodeWithoutPadding(p.getValueAsString());
+ return Base64.decode(p.getValueAsString());
}
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java
index 1fbd16a2da..f6f01aebba 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/CdsiSocket.java
@@ -22,7 +22,7 @@ import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager;
import org.whispersystems.signalservice.internal.util.Hex;
import org.whispersystems.signalservice.internal.util.JsonUtil;
import org.whispersystems.signalservice.internal.util.Util;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -214,7 +214,7 @@ final class CdsiSocket {
}
private static String basicAuth(String username, String password) {
- return "Basic " + Base64.encodeBytes((username + ":" + password).getBytes(StandardCharsets.UTF_8));
+ return "Basic " + Base64.encodeWithPadding((username + ":" + password).getBytes(StandardCharsets.UTF_8));
}
private static Pair createTlsSocketFactory(TrustStore trustStore) {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java
index 0abb0e4840..72712a88dd 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/MessagingService.java
@@ -19,7 +19,7 @@ import org.whispersystems.signalservice.internal.util.Util;
import org.whispersystems.signalservice.internal.websocket.DefaultResponseMapper;
import org.whispersystems.signalservice.internal.websocket.ResponseMapper;
import org.whispersystems.signalservice.internal.websocket.WebSocketRequestMessage;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.security.SecureRandom;
import java.util.LinkedList;
@@ -74,7 +74,7 @@ public class MessagingService {
public Single> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent, boolean story) {
List headers = new LinkedList() {{
add("content-type:application/vnd.signal-messenger.mrm");
- add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess));
+ add("Unidentified-Access-Key:" + Base64.encodeWithPadding(joinedUnidentifiedAccess));
}};
String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s&story=%s", timestamp, online, urgent, story);
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java
index 034b8c4f9b..9e3ea5df32 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/storage/StorageKey.java
@@ -1,7 +1,7 @@
package org.whispersystems.signalservice.api.storage;
import org.whispersystems.signalservice.api.kbs.MasterKey;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import org.whispersystems.util.StringUtil;
import java.util.Arrays;
@@ -31,7 +31,7 @@ public final class StorageKey {
}
public StorageItemKey deriveItemKey(byte[] key) {
- return new StorageItemKey(derive("Item_" + Base64.encodeBytes(key)));
+ return new StorageItemKey(derive("Item_" + Base64.encodeWithPadding(key)));
}
private byte[] derive(String keyName) {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java
index 1f4c64d02c..1c6de11c05 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/IdempotencyKey.java
@@ -1,8 +1,8 @@
package org.whispersystems.signalservice.api.subscriptions;
+import org.signal.core.util.Base64;
import org.whispersystems.signalservice.api.util.Preconditions;
-import org.whispersystems.util.Base64UrlSafe;
import java.security.SecureRandom;
import java.util.Arrays;
@@ -25,7 +25,7 @@ public final class IdempotencyKey {
}
public String serialize() {
- return Base64UrlSafe.encodeBytes(bytes);
+ return Base64.encodeUrlSafeWithPadding(bytes);
}
public static IdempotencyKey fromBytes(byte[] bytes) {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java
index 082e86e778..856fbcf7de 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/subscriptions/SubscriberId.java
@@ -1,8 +1,8 @@
package org.whispersystems.signalservice.api.subscriptions;
+import org.signal.core.util.Base64;
import org.whispersystems.signalservice.api.util.Preconditions;
-import org.whispersystems.util.Base64UrlSafe;
import java.security.SecureRandom;
import java.util.Arrays;
@@ -27,7 +27,7 @@ public final class SubscriberId {
}
public @NonNull String serialize() {
- return Base64UrlSafe.encodeBytes(bytes);
+ return Base64.encodeUrlSafeWithPadding(bytes);
}
public static SubscriberId fromBytes(byte[] bytes) {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java
index c490ab62d2..48bd02f6d7 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java
@@ -1,6 +1,6 @@
package org.whispersystems.signalservice.internal.contacts.crypto;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.ByteArrayInputStream;
import java.security.InvalidAlgorithmParameterException;
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java
index b065a21ad0..4df8eab03f 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/BoostReceiptCredentialRequestJson.java
@@ -3,7 +3,7 @@ package org.whispersystems.signalservice.internal.push;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequest;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
class BoostReceiptCredentialRequestJson {
@JsonProperty("paymentIntentId")
@@ -17,7 +17,7 @@ class BoostReceiptCredentialRequestJson {
BoostReceiptCredentialRequestJson(String paymentIntentId, ReceiptCredentialRequest receiptCredentialRequest, DonationProcessor processor) {
this.paymentIntentId = paymentIntentId;
- this.receiptCredentialRequest = Base64.encodeBytes(receiptCredentialRequest.serialize());
+ this.receiptCredentialRequest = Base64.encodeWithPadding(receiptCredentialRequest.serialize());
this.processor = processor.getCode();
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt
index a2f696d509..38f1f9edab 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthRequest.kt
@@ -6,8 +6,8 @@
package org.whispersystems.signalservice.internal.push
import com.fasterxml.jackson.annotation.JsonCreator
+import org.signal.core.util.Base64
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialRequest
-import org.whispersystems.util.Base64
/**
* Request body to create a call link credential response.
@@ -19,7 +19,7 @@ data class CreateCallLinkAuthRequest @JsonCreator constructor(
@JvmStatic
fun create(createCallLinkCredentialRequest: CreateCallLinkCredentialRequest): CreateCallLinkAuthRequest {
return CreateCallLinkAuthRequest(
- Base64.encodeBytes(createCallLinkCredentialRequest.serialize())
+ Base64.encodeWithPadding(createCallLinkCredentialRequest.serialize())
)
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt
index 544f6d5184..63d1c289ec 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/CreateCallLinkAuthResponse.kt
@@ -7,8 +7,8 @@ package org.whispersystems.signalservice.internal.push
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
+import org.signal.core.util.Base64
import org.signal.libsignal.zkgroup.calllinks.CreateCallLinkCredentialResponse
-import org.whispersystems.util.Base64
/**
* Response body for CreateCallLinkAuthResponse
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java
index cb57ddae90..669f30bf51 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/IdentityCheckRequest.java
@@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.signal.libsignal.protocol.IdentityKey;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.internal.util.JsonUtil;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -40,7 +40,7 @@ public class IdentityCheckRequest {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
- this.fingerprint = Base64.encodeBytes(messageDigest.digest(identityKey.serialize()), 0, 4);
+ this.fingerprint = Base64.encodeWithPadding(messageDigest.digest(identityKey.serialize()), 0, 4);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java
index 7668d549a1..90520fc3f3 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/KyberPreKeyEntity.java
@@ -18,7 +18,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.kem.KEMPublicKey;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
@@ -60,7 +60,7 @@ public class KyberPreKeyEntity {
private static class KEMPublicKeySerializer extends JsonSerializer {
@Override
public void serialize(KEMPublicKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize()));
+ gen.writeString(Base64.encodeWithoutPadding(value.serialize()));
}
}
@@ -68,7 +68,7 @@ public class KyberPreKeyEntity {
@Override
public KEMPublicKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
- return new KEMPublicKey(Base64.decodeWithoutPadding(p.getValueAsString()), 0);
+ return new KEMPublicKey(Base64.decode(p.getValueAsString()), 0);
} catch (InvalidKeyException e) {
throw new IOException(e);
}
@@ -78,7 +78,7 @@ public class KyberPreKeyEntity {
private static class ByteArraySerializer extends JsonSerializer {
@Override
public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytesWithoutPadding(value));
+ gen.writeString(Base64.encodeWithoutPadding(value));
}
}
@@ -86,7 +86,7 @@ public class KyberPreKeyEntity {
@Override
public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
- return Base64.decodeWithoutPadding(p.getValueAsString());
+ return Base64.decode(p.getValueAsString());
}
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java
index 37d771233b..488f62d119 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PreKeyEntity.java
@@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECPublicKey;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
@@ -51,7 +51,7 @@ public class PreKeyEntity {
private static class ECPublicKeySerializer extends JsonSerializer {
@Override
public void serialize(ECPublicKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize()));
+ gen.writeString(Base64.encodeWithoutPadding(value.serialize()));
}
}
@@ -59,7 +59,7 @@ public class PreKeyEntity {
@Override
public ECPublicKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
- return Curve.decodePoint(Base64.decodeWithoutPadding(p.getValueAsString()), 0);
+ return Curve.decodePoint(Base64.decode(p.getValueAsString()), 0);
} catch (InvalidKeyException e) {
throw new IOException(e);
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java
index b894218aa2..074b8bd0b5 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java
@@ -142,8 +142,7 @@ import org.whispersystems.signalservice.internal.util.concurrent.FutureTransform
import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture;
import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture;
import org.whispersystems.signalservice.internal.websocket.ResponseMapper;
-import org.whispersystems.util.Base64;
-import org.whispersystems.util.Base64UrlSafe;
+import org.signal.core.util.Base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -429,8 +428,8 @@ public class PushServiceSocket {
RegistrationSessionRequestBody body = new RegistrationSessionRequestBody(sessionId,
recoveryPassword,
attributes,
- Base64.encodeBytesWithoutPadding(aciPreKeys.getIdentityKey().serialize()),
- Base64.encodeBytesWithoutPadding(pniPreKeys.getIdentityKey().serialize()),
+ Base64.encodeWithoutPadding(aciPreKeys.getIdentityKey().serialize()),
+ Base64.encodeWithoutPadding(pniPreKeys.getIdentityKey().serialize()),
aciSignedPreKey,
pniSignedPreKey,
aciLastResortKyberPreKey,
@@ -510,7 +509,7 @@ public class PushServiceSocket {
public void sendProvisioningMessage(String destination, byte[] body) throws IOException {
makeServiceRequest(String.format(PROVISIONING_MESSAGE_PATH, destination), "PUT",
- JsonUtil.toJson(new ProvisioningMessage(Base64.encodeBytes(body))));
+ JsonUtil.toJson(new ProvisioningMessage(Base64.encodeWithPadding(body))));
}
public void registerGcmId(@Nonnull String gcmRegistrationId) throws IOException {
@@ -560,7 +559,7 @@ public class PushServiceSocket {
Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path));
requestBuilder.put(RequestBody.create(MediaType.get("application/vnd.signal-messenger.mrm"), body));
- requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeBytes(joinedUnidentifiedAccess));
+ requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeWithPadding(joinedUnidentifiedAccess));
if (signalAgent != null) {
requestBuilder.addHeader("X-Signal-Agent", signalAgent);
@@ -1071,7 +1070,7 @@ public class PushServiceSocket {
byte[] proof = Username.generateProof(username, randomness);
ConfirmUsernameRequest confirmUsernameRequest = new ConfirmUsernameRequest(reserveUsernameResponse.getUsernameHash(),
- Base64UrlSafe.encodeBytesWithoutPadding(proof));
+ Base64.encodeUrlSafeWithoutPadding(proof));
makeServiceRequest(CONFIRM_USERNAME_PATH, "PUT", JsonUtil.toJson(confirmUsernameRequest), NO_HEADERS, (responseCode, body) -> {
switch (responseCode) {
@@ -1115,7 +1114,7 @@ public class PushServiceSocket {
String response = makeServiceRequestWithoutAuthentication(String.format(USERNAME_FROM_LINK_PATH, serverId.toString()), "GET", null);
GetUsernameFromLinkResponseBody parsed = JsonUtil.fromJson(response, GetUsernameFromLinkResponseBody.class);
- return Base64UrlSafe.decodePaddingAgnostic(parsed.getUsernameLinkEncryptedValue());
+ return Base64.decode(parsed.getUsernameLinkEncryptedValue());
}
public void deleteAccount() throws IOException {
@@ -1137,7 +1136,7 @@ public class PushServiceSocket {
}
public void redeemDonationReceipt(ReceiptCredentialPresentation receiptCredentialPresentation, boolean visible, boolean primary) throws IOException {
- String payload = JsonUtil.toJson(new RedeemReceiptRequest(Base64.encodeBytes(receiptCredentialPresentation.serialize()), visible, primary));
+ String payload = JsonUtil.toJson(new RedeemReceiptRequest(Base64.encodeWithPadding(receiptCredentialPresentation.serialize()), visible, primary));
makeServiceRequest(DONATION_REDEEM_RECEIPT, "POST", payload);
}
@@ -2097,7 +2096,7 @@ public class PushServiceSocket {
if (!headers.containsKey("Authorization") && !doNotAddAuthenticationOrUnidentifiedAccessKey) {
if (unidentifiedAccess.isPresent()) {
- request.addHeader("Unidentified-Access-Key", Base64.encodeBytes(unidentifiedAccess.get().getUnidentifiedAccessKey()));
+ request.addHeader("Unidentified-Access-Key", Base64.encodeWithPadding(unidentifiedAccess.get().getUnidentifiedAccessKey()));
} else if (credentialsProvider.getPassword() != null) {
request.addHeader("Authorization", getAuthorizationHeader(credentialsProvider));
}
@@ -2395,7 +2394,7 @@ public class PushServiceSocket {
if (credentialsProvider.getDeviceId() != SignalServiceAddress.DEFAULT_DEVICE_ID) {
identifier += "." + credentialsProvider.getDeviceId();
}
- return "Basic " + Base64.encodeBytes((identifier + ":" + credentialsProvider.getPassword()).getBytes("UTF-8"));
+ return "Basic " + Base64.encodeWithPadding((identifier + ":" + credentialsProvider.getPassword()).getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
@@ -2663,7 +2662,7 @@ public class PushServiceSocket {
String path;
if (groupLinkPassword.isPresent()) {
- path = String.format(GROUPSV2_GROUP_PASSWORD, Base64UrlSafe.encodeBytesWithoutPadding(groupLinkPassword.get()));
+ path = String.format(GROUPSV2_GROUP_PASSWORD, Base64.encodeUrlSafeWithoutPadding(groupLinkPassword.get()));
} else {
path = GROUPSV2_GROUP;
}
@@ -2719,7 +2718,7 @@ public class PushServiceSocket {
public GroupJoinInfo getGroupJoinInfo(Optional groupLinkPassword, GroupsV2AuthorizationString authorization)
throws NonSuccessfulResponseCodeException, PushNetworkException, IOException, MalformedResponseException
{
- String passwordParam = groupLinkPassword.map(Base64UrlSafe::encodeBytesWithoutPadding).orElse("");
+ String passwordParam = groupLinkPassword.map(org.signal.core.util.Base64::encodeUrlSafeWithoutPadding).orElse("");
try (Response response = makeStorageRequest(authorization.toString(),
String.format(GROUPSV2_GROUP_JOIN, passwordParam),
"GET",
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java
index cd5037ce94..9d33692998 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialRequestJson.java
@@ -3,13 +3,13 @@ package org.whispersystems.signalservice.internal.push;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialRequest;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
class ReceiptCredentialRequestJson {
@JsonProperty("receiptCredentialRequest")
private final String receiptCredentialRequest;
ReceiptCredentialRequestJson(ReceiptCredentialRequest receiptCredentialRequest) {
- this.receiptCredentialRequest = Base64.encodeBytes(receiptCredentialRequest.serialize());
+ this.receiptCredentialRequest = Base64.encodeWithPadding(receiptCredentialRequest.serialize());
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java
index 97cc722c75..e3f839b647 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ReceiptCredentialResponseJson.java
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.receipts.ReceiptCredentialResponse;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java
index 255282c226..1bda288c91 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SenderCertificate.java
@@ -11,7 +11,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
@@ -31,7 +31,7 @@ public class SenderCertificate {
public static class ByteArraySerializer extends JsonSerializer {
@Override
public void serialize(byte[] value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytes(value));
+ gen.writeString(Base64.encodeWithPadding(value));
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java
index 69c2a20472..c1f28c4edf 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/http/ResumableUploadSpec.java
@@ -2,7 +2,7 @@ package org.whispersystems.signalservice.internal.push.http;
import org.signal.protos.resumableuploads.ResumableUpload;
import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.util.HashMap;
@@ -85,7 +85,7 @@ public final class ResumableUploadSpec {
.collect(Collectors.toList())
);
- return Base64.encodeBytes(builder.build().encode());
+ return Base64.encodeWithPadding(builder.build().encode());
}
public static ResumableUploadSpec deserialize(String serializedSpec) throws ResumeLocationInvalidException {
diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java
index 05fd09ed60..052d5eb3fc 100644
--- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java
+++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/util/JsonUtil.java
@@ -27,7 +27,7 @@ import org.whispersystems.signalservice.api.push.ServiceId.ACI;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
import org.whispersystems.signalservice.api.util.UuidUtil;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.util.UUID;
@@ -98,7 +98,7 @@ public class JsonUtil {
public void serialize(IdentityKey value, JsonGenerator gen, SerializerProvider serializers)
throws IOException
{
- gen.writeString(Base64.encodeBytesWithoutPadding(value.serialize()));
+ gen.writeString(Base64.encodeWithoutPadding(value.serialize()));
}
}
@@ -106,7 +106,7 @@ public class JsonUtil {
@Override
public IdentityKey deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
try {
- return new IdentityKey(Base64.decodeWithoutPadding(p.getValueAsString()), 0);
+ return new IdentityKey(Base64.decode(p.getValueAsString()), 0);
} catch (InvalidKeyException e) {
throw new IOException(e);
}
@@ -164,7 +164,7 @@ public class JsonUtil {
public static class MasterKeySerializer extends JsonSerializer {
@Override
public void serialize(MasterKey value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString(Base64.encodeBytes(value.serialize()));
+ gen.writeString(Base64.encodeWithPadding(value.serialize()));
}
}
diff --git a/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java b/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java
deleted file mode 100644
index 5c42b7569e..0000000000
--- a/libsignal-service/src/main/java/org/whispersystems/util/Base64UrlSafe.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.whispersystems.util;
-
-import java.io.IOException;
-
-public final class Base64UrlSafe {
-
- private Base64UrlSafe() {
- }
-
- public static byte[] decode(String s) throws IOException {
- return Base64.decode(s, Base64.URL_SAFE);
- }
-
- public static byte[] decodePaddingAgnostic(String s) throws IOException {
- switch (s.length() % 4) {
- case 1:
- case 3: s = s + "="; break;
- case 2: s = s + "=="; break;
- }
- return decode(s);
- }
-
- public static String encodeBytes(byte[] source) {
- try {
- return Base64.encodeBytes(source, Base64.URL_SAFE);
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- public static String encodeBytesWithoutPadding(byte[] source) {
- return encodeBytes(source).replace("=", "");
- }
-}
diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java
index 638b4b87b7..6c823ac8a3 100644
--- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java
+++ b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/ProfileCipherTest.java
@@ -6,7 +6,7 @@ import org.junit.Test;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
import org.whispersystems.signalservice.internal.util.Util;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -120,7 +120,7 @@ public class ProfileCipherTest {
ProfileCipher cipher = new ProfileCipher(key);
byte[] name = cipher.encrypt("Peter\0Parker".getBytes(), 53);
- String encoded = Base64.encodeBytes(name);
+ String encoded = Base64.encodeWithPadding(name);
assertEquals(108, encoded.length());
}
@@ -131,7 +131,7 @@ public class ProfileCipherTest {
ProfileCipher cipher = new ProfileCipher(key);
byte[] name = cipher.encrypt("Peter\0Parker".getBytes(), 257);
- String encoded = Base64.encodeBytes(name);
+ String encoded = Base64.encodeWithPadding(name);
assertEquals(380, encoded.length());
}
diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java
index d5efbcebbd..de5cf5bdda 100644
--- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java
+++ b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java
@@ -4,7 +4,7 @@ import junit.framework.TestCase;
import org.conscrypt.Conscrypt;
import org.whispersystems.signalservice.internal.contacts.crypto.SigningCertificate;
-import org.whispersystems.util.Base64;
+import org.signal.core.util.Base64;
import java.io.IOException;
import java.net.URLDecoder;
@@ -54,7 +54,7 @@ public class SigningCertificateTest extends TestCase {
malformedSignature[i] ^= (0x01 << j);
try {
- certificate.verifySignature(signatureBody, Base64.encodeBytes(malformedSignature));
+ certificate.verifySignature(signatureBody, Base64.encodeWithPadding(malformedSignature));
throw new AssertionError("Signature verification should fail!");
} catch (SignatureException e) {
// good
diff --git a/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java b/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java
deleted file mode 100644
index be61b61971..0000000000
--- a/libsignal-service/src/test/java/org/whispersystems/util/Base64UrlSafeTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.whispersystems.util;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.whispersystems.signalservice.internal.util.Hex;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-
-@RunWith(Parameterized.class)
-public final class Base64UrlSafeTest {
-
- private final byte[] data;
- private final String encoded;
- private final String encodedWithoutPadding;
-
- @Parameterized.Parameters
- public static Collection