2

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/

Pathos
  • 399
  • 4
  • 16
  • 1
    Ok I got it working now. The problem was that I tried to work with the apns-dev-key.p12. But all I need to do is use the push cert (p12 file including the cert and the key) and use the password I created when exporting the cert. – Pathos Feb 23 '12 at 10:38

2 Answers2

3

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".

Pathos
  • 399
  • 4
  • 16
0

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.

Sylvain P.
  • 249
  • 2
  • 4