Pathos
Pathos

Reputation: 399

SSL handshake with Apple Push Notification Server via Java

Hello I am trying to send a push message to my device using Java. But I'am allready getting problems when establishing the ssl connection. Here is the code so far:

        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        InputStream key = getClass().getResourceAsStream("apns-dev-key.p12");
        char[] c = key.toString().toCharArray();

        keyStore.load(getClass().getResourceAsStream("apns-dev-cert.p12"), c);
        KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
        keyMgrFactory.init(keyStore, c);

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyMgrFactory.getKeyManagers(), null, null);
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(host, port);
        String[] cipherSuites = sslSocket.getSupportedCipherSuites();
        sslSocket.setEnabledCipherSuites(cipherSuites);
        sslSocket.startHandshake();

The error I am getting is:

java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded

I guess there is some problem with the apns-dev-key.p12 file. Any hints?

The code above is taken from: http://undermypalapa.wordpress.com/2009/08/23/apple-push-notification-service-java/

Upvotes: 2

Views: 7450

Answers (2)

Sylvain P.
Sylvain P.

Reputation: 249

You might want to take a look at http://code.google.com/p/javapns/. If you really need to reinvent the wheel and not use JavaPNS directly instead of writing your own code for this, at least JavaPNS' documentation should help you understand key principles you'll need to know.

Upvotes: 0

Pathos
Pathos

Reputation: 399

Here my working example:

private String token = "<token>";
private String host = "gateway.sandbox.push.apple.com";
private int port = 2195;

private String payload = "{\"aps\":{\"alert\":\"Message from Java o_O\"}}";

public APNSender() {
    try {
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        keyStore.load(getClass().getResourceAsStream("cert.p12"), "<password>".toCharArray());
        KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance("SunX509");
        keyMgrFactory.init(keyStore, "<password>".toCharArray());

        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyMgrFactory.getKeyManagers(), null, null);
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

        SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(host, port);
        String[] cipherSuites = sslSocket.getSupportedCipherSuites();
        sslSocket.setEnabledCipherSuites(cipherSuites);
        sslSocket.startHandshake();

        char[] t = token.toCharArray();
        byte[] b = Hex.decodeHex(t);

        OutputStream outputstream = sslSocket.getOutputStream();

        outputstream.write(0);
        outputstream.write(0);
        outputstream.write(32);
        outputstream.write(b);
        outputstream.write(0);
        outputstream.write(payload.length());
        outputstream.write(payload.getBytes());

        outputstream.flush();
        outputstream.close();

    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

What I'm still curious about is how to receive error codes. I tried it with

InputStream in = sslSocket.getInputStream(); 
[...]   

but no success.

The Apple docs say that there is no answer send when no errors occured but on the other hand they list a status code for "No errors encountered".

Upvotes: 3

Related Questions