安全Socket

本文介绍了安全Socket的概念,探讨了使用JSSE进行Socket通信的加密机制,包括密钥生成、交换过程及会话管理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安全Socket


对Socket加密,保持事务的机密性、真实性、准确性。


保护通信


适合计算机实现的大多数加密机制都是基于密钥思想的,密钥是一种更加一般化的口令,并不限于文本。明文消息根据一种数学算法与密钥的各个位组合,生成加密的密文。使用的密钥位数越多,通过强力猜测密钥的方法来解密消息时就会越困难。


传统的秘密密钥(对称密钥)加密中,加密和解密数据都使用相同的密钥。


公开密钥加密中,加密和解密数据使用不同的密钥。

一个密钥称为公开密钥,用于加密数据。

另一个密钥称为私有密钥,用于解密数据。

私有密钥秘密保存,只有通信中的一方拥有它。

因为公开密钥加密是比较“CPU密集型”的操作,比秘密密钥加密慢得多。因此,不是用公开密钥加密整个传输内容,而是用它来加密传统的秘密密钥。


JSSE掩盖了如何协商算法、交换密钥、认证通信双方和加密数据的底层细节。JSSE允许你创建Socket和服务器Socket,可以透明地处理安全通信中必要的协商和加密。


创建安全客户端Socket


使用SSL Socket与现有的安全服务器通信确实非常简单。不是用构造函数来创造一个java.net.Socket对象,而是从javax.net.ssl.SSLSocketFactory使用其createSocket()方法得到一个Socket对象。要通过调用静态SSLSocketFactory.getDefault()方法得到一个实例:

SocketFactory factory = SSLSocketFactory.getDefault();

Socket socket = factory.createSocket(host,port);


五个重载的createSocket()方法:

Socket createSocket(String host, int port);

Socket createSocket(InetAddress host, int port);

Socket createSocket(String host, int port,InetAddress interface, int localport);

Socket createSocket(InetAddress host, int port,InetAddress interface, int localport)

Socket createSocket(Socket proxy,String host, int port, boolean autoClose);//autoClose参数确定当这个Socket关闭时,底层proxy Socket是否应当关闭。如果autoClosetrue,则底层Socket会关闭,否则,不关闭。


一旦创建了安全Socket,就可以像其他Socket一样使用。


**生成和交换密钥时,都有相当可观的CPU和网络开销,因此,不是希望所有内容都通过HTTPS提供,只有确实需要保证秘密而且不太关心延迟的内容才会通过HTTPS传输。


选择密码组


SSLSocketFactory中的

getSupportedCipherSuites()方法可以指出给定Socket上可用的算法组合。

getEnabledCipherSuites()方法可以指出这个Socket允许使用哪些密码组。

setEnabledCipherSuites(String[] suites)方法修改客户端试图使用的密码组。

以TLS_ECDHE开头并以SHA256或SHA348结尾的密码组是当前广泛使用的最强的加密算法。


DES/AES是块加密,DES总是加密64位,不足64位,编码器必须用额外的位填充输入。

AES可以加密128、192、256位的块,如果不是块的整数倍,仍然要填充输入。


事件处理器

安全连接所必需的密钥生成和建立过程会轻而易举的花费数秒钟时间,可能需要异步处理连接。

JSSE使用标准java事件模型来通知程序,告诉它们客户端和服务器之间的握手何时完成。实现HandshakeCOmpletedListener接口。

接口声明了handshakeCompleted()方法,此方法接受一个HandshakeCompletedEvent参数。

通过addHandshakeCompletedListener()h和removeHandshakeCompletedListener()方法,特定的HandshakeCompletedListener对象可以注册对某个SSLSocket的握手结束事件的关注。


会话管理

在很短的时间内对一台主机的一个端口打开多个安全Socket,JSSE会自动重用这个会话的密钥。

getSession()方法返回这个Socket所属的Session会话。

避免Socket创建会话,要向setEnableSessionCreation()传入false;

getEnableSessionCreation()返回true允许多Socket会话,返回false,不允许多Socket的会话。


客户端模式


setUseClientMode()方法确定Socket是否需要在第一次握手时使用认证。

客户端和服务端Socket都可以使用这个方法。传入true时,它表示Socket处于客户端模式,因此不提供自行认证。传入false时,则会尝试自行认证,只能设置一次。

getUseClientMode()方法只是告诉这个Socket是否会在第一次握手时使用认证。

服务器端的安全Socket可以使用setNeedClientAuth()方法,要求与它连接的所有客户端都要自行认证。

当需要认证时,getNeedClientAuth()方法返回true,否则返回false。


创建安全服务器Socket


SSLServerSocketFactory.getDefault();

createServerSocket(int port);

createServerSocket(int port, int queueLength);

createServerSocket(int port, int queueLength, InetAddress interface);

创建一个安全服务器Socket,必须完成以下步骤:

1.使用keytool生成公开密钥和证书。

2.花钱请可信任的第三方认证你的证书。

3.为你使用的算法创建一个SSLContext。

4.为你要使用的证书源创建一个TrustManagerFactory。

5.为你要使用的密钥类创建一个KeyManagerFactory.

6.为密钥和证书数据库创建一个KeyStore对象。

7.用密钥和证书填充KeyStore对象。

8.用KeyStore及其口令短语初始化KeyManagerFactory。

9.用KeyManagerFactory中的密钥管理器、TrustManagerFactory中的信任管理器和一个随机源来初始化上下文。


选择密码组


getSupportedCipherSuites()

getEnabledCipherSuites()

setEnabledCipherSuites(String[] auites)


会话管理


setEnableSessionCreation()

getEnableSessionCreation()



// C/C++, 利用OpenSSL库对Socket传输进行安全加密(RSA+AES) // 1. 利用RSA安全传输AES生成密钥所需的Seed(32字节) // 2. 利用AES_encrypt/AES_decrypt对Socket上面的业务数据进行AES加密/解密 // --- // * 理论上只需要AES就能保证全部流程,但由于AES加密所需要的AES-KEY是一个结构 // * 这个一个结构,如果通过网络进行传输,就需要对它进行网络编码,OpenSSL里面没有现成的API // * 所以就引入RSA来完成首次安全的传输,保证Seed不会被窃听 // * 同样,只使用RSA也能完成全部流程,但由于RSA的处理效率比AES低, // * 所以在业务数据传输加密上还是使用AES // --- // 下面的代码包含了上述传输加密流程所需的所有步骤(OpenSSL部分) // 在实际的Socket应用开发时,需要将这些步骤插入到Client/Server网络通信的特定阶段 // --- // 为能完成代码的编译和执行,需要先安装OpenSSL执行库及开发库 // 以Debian为例,需要安装openssl 和 libssl-dev // 编译命令: g++ -o rsa-encrypt rsa-encrypt.cpp -lcrypto // --- // 所需的OpenSSL主要的API及功能描述 // 1. RSA_generate_key() 随机生成一个RSA密钥对,供RSA加密/解密使用 // 2. i2d_RSAPublicKey() 将RSA密钥对里面的公钥提出到一个BUF,用于网络传输给对方 // 3. d2i_RSAPublicKey() 将从网络传过来的公钥信息生成一个加密使用的RSA(它里面只有公钥) // 4. RSA_public_encrypt() 使用RSA的公钥对数据进行加密 // 5. RSA_private_decrypt() 使用RSA的私钥对数据进行加密 // 6. AES_set_encrypt_key() 根据Seed生成AES密钥对中的加密密钥 // 7. AES_set_decrypt_key() 根据Seed生成AES密钥对中的解密密钥 // 8. AES_encrypt() 使用AES加密密钥对数据进行加密 // 9. AES_decrypt() 使用AES解密密钥对数据进行解密 // --- // 一个典型的安全Socket的建立流程, 其实就是如何将Server随机Seed安全发给Client // -- C: Client S:Server // C: RSA_generate_key() --> RSAKey --> i2d_RSAPublicKey(RSAKey) --> RSAPublicKey // C: Send(RSAPublicKey) TO Server // S: Recv() --> RSAPublicKey --> d2i_RSAPublicKey(RSAPublicKey) --> RSAKey // S: Rand() --> Seed --> RSA_public_encrypt(RSAKey, Seed) --> EncryptedSeed // S: Send(EncryptedSeed) TO Client // C: Recv() --> EncryptedSeed --> RSA_private_decrypt(RSAKey, EncryptedSeed) --> Seed // --- 到此, Client和Server已经完成完成传输Seed的处理 // --- 后面的流程是它们怎样使用这个Seed来进行业务数据的安全传输 // C: AES_set_encrypt_key(Seed) --> AESEncryptKey // C: AES_set_decrypt_key(Seed) --> AESDecryptKey // S: AES_set_encrypt_key(Seed) --> AESEncryptKey // S: AES_set_decrypt_key(Seed) --> AESDecryptKey // --- Client传输数据给Server // C: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> Server // S: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data // --- Server传输数据给Client // S: AES_encrypt(AESEncryptKey, Data) --> EncryptedData --> Send() --> Client // C: Recv() --> EncryptedData --> AES_decrypt(AESDecryptKey, EncryptedData) --> Data / ========================================================================================= */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值