8

我正在尝试通过 SSL 与服务器通信。PEM 客户端文件由证书和 rsa 私钥组成。

我设法将证书和密钥都转换为二进制 DER。我成功地将 DER 证书加载到 SecureSocket(使用函数 addBinaryChainBuildingCertificate),但是当我尝试连接到服务器时,出现“主要不匹配”错误。如果我尝试使用上述函数加载 DER 密钥,则会收到“错误参数”错误。

我想“主要不匹配”是因为我没有加载私钥。但我看不到将 RSA 密钥加载到 SecureSocket 的功能。有什么解决办法吗?我是否需要仅使用证书与服务器通信,但从等式中删除密钥?

编辑 :

代码 :

package {

    import flash.display.Sprite;
    import flash.net.SecureSocket;
    import flash.net.URLLoader;
    import flash.events.ProgressEvent;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.net.URLLoaderDataFormat;
    import flash.net.URLRequest;
    import flash.utils.ByteArray;

    public class TestSSL2 extends Sprite {

        private var mSocket:SecureSocket = new SecureSocket();

        private var certFile:String = "ca.der";
        private var keyFile:String = "key.der";

        private var cert:ByteArray;
        private var key:ByteArray;

        public function TestSSL2() {
            trace("SecureSocket.isSupported",SecureSocket.isSupported);

            var urlLoader:URLLoader = new URLLoader();
            urlLoader.addEventListener(Event.COMPLETE, certLoaded, false, 0, true);
            urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
            urlLoader.load(new URLRequest(certFile));
        }
        private function certLoaded(e:Event):void {
            cert = (e.target as URLLoader).data;
            trace("certificate",cert.length);
            mSocket.addBinaryChainBuildingCertificate(cert, true);

            var urlLoader:URLLoader = new URLLoader();
            urlLoader.addEventListener(Event.COMPLETE, keyLoaded, false, 0, true);
            urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
            urlLoader.load(new URLRequest(keyFile));
        }
        private function keyLoaded(e:Event):void {
            key = (e.target as URLLoader).data;
            trace("key",key.length);
            mSocket.addBinaryChainBuildingCertificate(key, true);

            mSocket.connect("127.0.0.1", 3000);
            mSocket.addEventListener(Event.CONNECT, socketConnected);
            mSocket.addEventListener(IOErrorEvent.IO_ERROR, onError);
            mSocket.addEventListener(ProgressEvent.SOCKET_DATA, socketData );
        }

        private function onError(error:IOErrorEvent):void {
            trace("ERROR!",error.text,":",mSocket.serverCertificateStatus);
        }

        private function socketConnected(e:Event):void {
            trace("Connected", e);
        }

        private function socketData(e:*):void {
            var data:String;
            data = mSocket.readUTFBytes(mSocket.bytesAvailable);
            trace(data);
        }
    }

}

结果 :

SecureSocket.isSupported true
certificate 497
key 607
ArgumentError: Error #2004: One of the parameters is invalid.
    at flash.net::SecureSocket/addBinaryChainBuildingCertificate()
    at TestSSL2/keyLoaded()
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at flash.net::URLLoader/onComplete()

如果我评论该行:

//mSocket.addBinaryChainBuildingCertificate(key, true);

我得到:

SecureSocket.isSupported true
certificate 497
key 607
ERROR! Error #2031: Socket Error. URL: 127.0.0.1 : principalMismatch
4

1 回答 1

3

首先:

“主体不匹配”表示受保护服务器上证书的公用名称与您要连接的 DNS 名称不匹配。

考虑到您正在连接到 localhost (127.0.0.1),肯定会有不匹配的情况。Flash 套接字在建立安全连接时特别严格,并且与其他运行时(例如 .NET 和 Java)不同,没有覆盖安全功能的机制。以下内容必须为真:

  1. 证书公用名必须与 DNS 名称匹配(这里对“星”证书有一个放宽,即*.bob.com认为对 的证书有效mr.bob.com
  2. 证书必须在到期和信任链方面有效

第二:

您似乎对证书的工作方式有一些误解。addBinaryChainBuildingCertificate()如果服务器证书是由受信任的根颁发机构颁发的,即签署服务器证书的证书在目标设备的本地信任库中,则不需要使用该方法添加任何证书。

为了显示:

  • 我有一个this.is.awesome.com安装在我的服务器上的证书和一个解析this.is.awesome.com为我的服务器 IP 地址的 DNS 条目
  • 此证书由 Entrust L1C 证书颁发机构颁发。
  • L1C 证书又由 Entrust 2048 根机构颁发。

在我的 PC 上,我的可信根证书存储中安装了 Entrust 2048 根权限。但是我没有安装 L1C 证书。当我尝试连接时this.is.awesome.com,连接将失败,因为无法针对 L1C 授权验证服务器证书。

如果我使用添加 DER 编码的 L1C 证书,addBinaryChainBuildingCertificate()则连接将成功。服务器证书将根据 L1C 证书进行验证,而 L1C 证书将根据 2048 根证书进行验证,该证书是受信任的根。

总结一下:

您的连接问题似乎源于您尝试连接到 localhost。尝试在 HOSTS 文件中添加一个条目,将证书上的名称映射到 127.0.0.1,然后连接到该名称。如果失败,请检查证书上的颁发者链,并通过为链中的addBinaryChainBuildingCertificate()每个颁发证书调用一次来添加颁发者链。最终证书或根证书应通过true作为第二个参数传递给addBinaryChainBuildingCertificate()

于 2012-11-21T05:56:08.537 回答