【问题标题】:SSL handshake with Apple Push Notification Server via Java通过 Java 与 Apple Push Notification Server 进行 SSL 握手
【发布时间】:2012-02-23 09:31:06
【问题描述】:

您好,我正在尝试使用 Java 向我的设备发送推送消息。但是在建立 ssl 连接时我已经遇到了问题。 到目前为止的代码如下:

        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();

我得到的错误是:

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

我猜apns-dev-key.p12 文件有问题。有什么提示吗?

以上代码摘自:http://undermypalapa.wordpress.com/2009/08/23/apple-push-notification-service-java/

【问题讨论】:

  • 好的,我现在开始工作了。问题是我尝试使用 apns-dev-key.p12。但我需要做的就是使用推送证书(p12 文件,包括证书和密钥)并使用我在导出证书时创建的密码。

标签: java ssl apple-push-notifications


【解决方案1】:

这是我的工作示例:

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();
    }
}

我仍然好奇的是如何接收错误代码。我试过了

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

但没有成功。

Apple docs 表示在没有发生错误时不会发送应答,但另一方面,他们会列出“未遇到错误”的状态代码。

【讨论】:

  • 不要启用所有受支持的密码套件。其中一些默认情况下被禁用是有充分理由的。
  • 这也可以用 pem 完成吗?
【解决方案2】:

您可能想看看http://code.google.com/p/javapns/。如果你真的需要重新发明轮子而不是直接使用 JavaPNS 而不是为此编写自己的代码,那么至少 JavaPNS 的文档应该可以帮助你理解你需要知道的关键原则。

【讨论】:

    猜你喜欢
    • 2015-04-09
    • 2018-05-16
    • 2017-01-15
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    • 2013-01-14
    • 2017-01-27
    • 2012-08-08
    相关资源
    最近更新 更多