How to Compile and Run Open Whisper Systems’ Signal Server (TextSecure Server) (Part 2)

Last time, when I try to activate Signal Server, I got this:

D:\Projects\AndroidProgram\Signal\Server>java -jar target\TextSecureServer-1.65
.jar server config/textsecure.yml
null

So, it exited the loop, and only giving a “null” as an error message. This is the most cryptic error I’ve ever get in debugging experieces.

Checking the exact source of exception reveals it is java.lang.NullPointerException.

So, the call stack can be easily obtained by breaking into NullPointerException in the java sources:

And I have:

Let’s perform of analysis of this class:

APNSender apnSender = new APNSender(accountsManager, config.getApnConfiguration());

private static PrivateKey initializePrivateKey(String pemKey)

Let’s see the content of pemKey:

lkajsdf

The content of pemKey appears to be obtained from:

Since I just create the same dummy variables for the above configuration variables, let’s differentiate it, and I have that pemKey is initialized using pushKey configuration item:

PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(pemKey.getBytes())));

I assumed that to get the pushKey from Apple required some dollar involvement, so, let’s just create a dummy PEM Key just to make this class happy.

import org.bouncycastle.openssl.PEMReader

So, this is part of the utility created by bouncycastle, let’s get some information regarding this first. OK, so this is a PEM Certificate, let’s try to generate it:

C:\OpenSSL-Win32\bin>openssl genrsa -out rsa_1024_priv.pem 1024
Generating RSA private key, 1024 bit long modulus
………++++++
…..++++++
e is 65537 (0x10001)

Run the server, and I have:

D:\Projects\AndroidProgram\Signal\Server>java -Xdebug -Xrunjdwp:transport=dt_soc
ket,server=y,address=8880,suspend=y -jar target\TextSecureServer-1.65.jar serve
r config/textsecure.yml
Listening for transport dt_socket at address: 8880
—–END RSA PRIVATE KEY not found

No matter what I try to fiddle with the key, I got this same error message. I believe the format I’ve passed to the configuration is OK. But let’s see whether it is generated some exception again.

This time, I got java.io.IOException. Repeat the above procedure, I have:

But when I try to trap the IOException, there’s an interesting IOException just BEFORE this exception. So, let’s check it out first:

\C:\Program Files (x86)\Java\jdk1.8.0_131\jre\lib\sunrsasign.jar

Seems, it has some relation with RSA signing. From the findjar website, I’ve found that is already in rt.jar so, I think I’ll stop pursue this issue for the moment.

Let’s come back to the above rather persistent error message to understand what it try to process from the given private key.

Retrieve bouncycastle module sources from:

http://central.maven.org/maven2/org/bouncycastle/bcprov-jdk16/1.46

Which is the dependency currently used by my TextSecureServer java program at this moment.

But NetBeans complains as follows:

Not able to submit breakpoint LineBreakpoint PemReader.java : 54, reason: Line number information is missing in the class file org.bouncycastle.util.io.pem.PemReader.

Let’s verify:

This is the one that has line number information:

D:\temp\dw\io\dropwizard>javap -l application.class
Compiled from “Application.java”
public abstract class io.dropwizard.Application {
protected io.dropwizard.Application();
LineNumberTable:
line 25: 0
line 27: 4
line 28: 11

And indeed, the given class in the jar does not have line number information:

D:\temp\bc\org\bouncycastle\openssl>javap -l pemreader.class
public class org.bouncycastle.openssl.PEMReader extends org.bouncycastle.util.io
.pem.PemReader {
public org.bouncycastle.openssl.PEMReader(java.io.Reader);

public org.bouncycastle.openssl.PEMReader(java.io.Reader, org.bouncycastle.ope
nssl.PasswordFinder);

Try to find compatible environment for BouncyCastle’s version 1.46 compilation proves to be difficult. After perform some research, I decided to compile the version 1.57 instead.

D:\Projects\JavaProgram\BouncyCastle>gradlew build -x lint
Error: Could not find or load main class org.gradle.wrapper.GradleWrapperMain

This can be resolved by copying existing gradle folder in the usable projects into this project folder.

Now I have:

D:\Projects\JavaProgram\BouncyCastle>gradlew build -x lint
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reus
ed, use –status for details
0% CONFIGURING [42s]
> root project > Resolve dependencies :classpath > gradle-cobertura-plugin-2.2.

It failed to download the above package. So again, using proxy will alleviate the problem.

But the result of version 1.57 is somewhat vague, which has many JARs that is not compatible with the intended version.

So, I have to resort to create a customized gradle build system from older 1.46 sources in D:\Projects\JavaProgram\BouncyCastle2, and after a successful compile, I verify it that it is indeed it has line number information in it:

D:\temp>javap -l pemreader.class
Compiled from “PemReader.java”
public class org.bouncycastle.util.io.pem.PemReader extends java.io.BufferedRead
er {
public org.bouncycastle.util.io.pem.PemReader(java.io.Reader);
LineNumberTable:
line 19: 0
line 20: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lorg/bouncycastle/util/io/pem/PemReader;
0 6 1 reader Ljava/io/Reader;

So, now I try to replace the 1.46 version in my local maven repository and perform the recompiling.

But to my surprises, I found many errors.

This is strange, because the first time I try to compile it is a success. Why the second compilation process is not ?

First, I suspect maybe it is the cause of my replacing of BouncyCastle 1.46, so I revert back to the old jar and try to re-compile with exact same error message:


[ERROR] /D:/Projects/AndroidProgram/Signal/Server/src/main/java/java/util/function/LongUnaryOperator.java:[64,5] default methods are not supported in -source 1.7
(use -source 8 or higher to enable default methods)
[ERROR] /D:/Projects/AndroidProgram/Signal/Server/src/main/java/java/util/function/LongUnaryOperator.java:[66,25] lambda expressions are not supported in -source 1.7
(use -source 8 or higher to enable lambda expressions)
[ERROR] /D:/Projects/AndroidProgram/Signal/Server/src/main/java/java/util/function/LongUnaryOperator.java:[92,38] static interface methods are not supported in -source 1.7
(use -source 8 or higher to enable static interface methods)

Try to change the version as suggested by the error message, i.e change to 1.8 proves to be generated more cryptic errors. So I revert back to the old configuration, and I decided to compare the original sources to the one I try to re-compile, and I found mysterious java folder inside the sources I try to re-compile.

And suddenly I realized it is my mistake this time, because I accidentally use this source folder as a NetBeans debugging, and added unnecessary sources into the folder.

Next time I should place the debugging source files into another folder. After removing the offending folders, and try to recompile:

[INFO] ———————
[INFO] BUILD SUCCESS
[INFO] ———————

It is OK with the version 1.46 of BouncyCastle utility. So, let’s replace it now with one with line number information and see what happens when I try to re-compile, again it is a success.

To create a separate source, I created a new folder at D:\Projects\NetBeans\SignalServer to host the new location of NetBeans project.

After some studying of NetBeans to try to separate the sources for debugging and the actual program so that the above compiling error can be avoided, I realized, it is very difficult to achieve that condition.

Later on, I found that using “Remote Attach” to add new Source Root will solve the problem:

The Java and any other JARs that required source code debugging then can be placed into D:\Projects\NetBeans\Debug\src. Now, let’s start to analyze the BouncyCastle error.

First, I try to perform breakpoint at the PemReader’s loadObject, and here is the result:

The readLine function suddenly returning with null, so it end up with the —–END RSA PRIVATE KEY not found error. This indicated that the buffer is not received any of the data. Hmm, fishy.

After checking the readPemObject function of PemReader.java, I realized that the passed string should contain Carriage Return and Line Feed. But how to encode it into YAML object ?

Try to pass \r and \n proves to be futile, because readLine inside this function returns one line:

After some study of YAML using this format will solve the issue:

Now I have:

D:\Projects\AndroidProgram\Signal\Server>java -jar target\TextSecureServer-1.65.
jar server config/textsecure.yml
org/eclipse/jetty/alpn/ALPN$Provider

The cause of the above exit is java.lang.NoClassDefFoundError. Try to perform break point, I have:

at java.lang.NoClassDefFoundError.(NoClassDefFoundError.java:59)
at io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator$1.(JdkAlpnApplicationProtocolNegotiator.java:26)
at io.netty.handler.ssl.JdkAlpnApplicationProtocolNegotiator.(JdkAlpnApplicationProtocolNegotiator.java:24)
at io.netty.handler.ssl.JdkSslContext.toNegotiator(JdkSslContext.java:285)
at io.netty.handler.ssl.JdkSslClientContext.(JdkSslClientContext.java:261)
at io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:751)
at io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:418)
at com.relayrides.pushy.apns.ApnsClientBuilder.build(ApnsClientBuilder.java:408)
at org.whispersystems.textsecuregcm.push.RetryingApnsClient.(RetryingApnsClient.java:63)
at org.whispersystems.textsecuregcm.push.APNSender.(APNSender.java:61)
at org.whispersystems.textsecuregcm.WhisperServerService.run(WhisperServerService.java:176)
at org.whispersystems.textsecuregcm.WhisperServerService.run(WhisperServerService.java:111)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:43)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:85)
at io.dropwizard.cli.Cli.run(Cli.java:74)
at io.dropwizard.Application.run(Application.java:89)
at org.whispersystems.textsecuregcm.WhisperServerService.main(WhisperServerService.java:276)

The above exception is tripped by the statement:

if (!JdkAlpnSslEngine.isAvailable()) in JdkAlpnApplicationProtocolNegotiator.java, which is caused by un-initialized JdkAlpnSslEngine

But why it has connection to the above org/eclipse/jetty/alpn/ALPN$Provider ? Checking the source code of JdkAlpnSslEngine.java, it is indeed there’s reference to this class:

import org.eclipse.jetty.alpn.ALPN

Performing checking to the binary JARs also confirm the non-existent of this class.

Some statement from the web regarding this issue in https://stackoverflow.com/questions/39856972/http-2-java-8-jetty-and-alpn:

Jetty’s ALPN boot jar works with both OpenJDK and Oracle’s JDK (which is based on OpenJDK).

Jetty’s ALPN boot jar must be in the boot classpath, not the regular classpath, like the documentation you linked says.

As such, you must not declare it as a dependency in your pom.xml files (there is no need to, like there is no need for you to specify a dependency on the JDK classes).

JDK 9 will have ALPN support native, there is already some work in that direction.

For java version java version “1.8.0_131” requires 8.1.11.v20170118.

Configuring command line to:

java -Xbootclasspath/p:target\alpn-boot-8.1.11.v20170118.jar -jar target\TextSecureServer-1.65.jar server config/textsecure.yml

D:\Projects\AndroidProgram\Signal\Server>java -Xbootclasspath/p:target\alpn-boot
-8.1.11.v20170118.jar -jar target\TextSecureServer-1.65.jar server config/textse
cure.yml

Will solve this issue, but now the server is continuous loop. But seems there’s no information, logs or anything to indicate what is it that is doing. Using ProcMon to find out interesting files created reveals:

D:\tmp\textsecureshserver.log

Inside this file is a wealth of information regarding the server’s activities. Hmm, good job Open Whisper Systems. Although there’s some issue should be fixed, for example a more friendly error message and some initial information of where to search vital information such as log, etc.

But I think this is the way how open source community works.

After a while, the server stops by itself:

D:\Projects\AndroidProgram\Signal\Server>java -Xbootclasspath/p:target\alpn-boot
-8.1.11.v20170118.jar -jar target\TextSecureServer-1.65.jar server config/textse
cure.yml
Multiple exceptions

Hmm, interesting, but I will stop for the moment.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: