• （1）实现基于DES和RSA算法的自动分配密钥加密聊天程序。 （2）实现密钥自动生成，并基于RSA算法进行密钥共享。 （3）实现基于DES加密的全双工通信，并且加密过程对用户是透明的。 提示：以下是本篇文章正文内容，...


文章目录实现的功能一、安全加密模型二、代码三、运行结果总结

实现的功能

（1）实现基于DES和RSA算法的自动分配密钥加密聊天程序。
（2）实现密钥自动生成，并基于RSA算法进行密钥共享。
（3）实现基于DES加密的全双工通信，并且加密过程对用户是透明的。

一、安全加密模型

在这个模型中 E()代表加密，D()代表解密，我们要的是发方与收方之间的加密通信，这个加密通信是基于DES加密的，DES加密是对称加密（收发两方使用的秘钥相同），发方会产生DES秘钥，但是DES秘钥要怎么传递给收方呢？ 这就要用到RSA非对称加密，直白的说，使用RSA加密就是加密的发放的秘钥。
RSA是非对称加密，发方使用收方的公钥加密自己的DES秘钥，然后传递给收方，收方再用自己的RSA私钥进行解密，获得DES秘钥。

二、代码
DES_BOX.py
# !/usr/bin/python3
# 说明:  DES中用到的盒

IP_table = [58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7]

IP_re_table = [40,8, 48, 16, 56, 24, 64, 32, 39,
7, 47, 15, 55, 23, 63, 31, 38, 6,
46, 14, 54, 22, 62, 30, 37,5, 45,
13, 53, 21, 61, 29, 36, 4, 44, 12,
52, 20, 60, 28, 35, 3, 43, 11, 51,
19, 59, 27, 34, 2, 42, 10, 50, 18,
58, 26, 33, 1, 41,9, 49, 17, 57, 25]

E  = [32, 1,  2,  3,  4,  5,  4,  5,
6, 7,  8,  9,  8,  9, 10, 11,
12,13, 12, 13, 14, 15, 16, 17,
16,17, 18, 19, 20, 21, 20, 21,
22, 23, 24, 25,24, 25, 26, 27,
28, 29,28, 29, 30, 31, 32,  1]

P = [16,  7, 20, 21, 29, 12, 28, 17,
1, 15, 23, 26,  5, 18, 31, 10,
2,  8, 24, 14, 32, 27,  3,  9,
19, 13, 30, 6, 22, 11,  4,  25]

S =  [
[14, 4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13 ],

[15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9],

[10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12 ],

[7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11,  12,  4, 15,
13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,9,
10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14],

[2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3],

[12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13],

[4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12],

[13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11],

]

#key

PC_1 = [57, 49, 41, 33, 25, 17,9,
1, 58, 50, 42, 34, 26, 18,
10,  2, 59, 51, 43, 35, 27,
19, 11,  3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22,
14,  6, 61, 53, 45, 37, 29,
21, 13,  5, 28, 20, 12, 4]

PC_2 = [14, 17, 11, 24,  1,  5,  3, 28,
15,  6, 21, 10, 23, 19, 12,  4,
26,  8, 16,  7, 27, 20, 13,  2,
41, 52, 31, 37, 47, 55, 30, 40,
51, 45, 33, 48, 44, 49, 39, 56,
34, 53, 46, 42, 50, 36, 29, 32]

#秘钥左移的位数
SHIFT = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]


test_rsa.py
from random import randrange
RSA_DEFAULT_EXPONENT = 65537
RSA_DEFAULT_MODULUS_LEN = 2048

first_50_primes = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229, 233]

def generate_n_bit_odd(n: int):
'''Generate a random odd number in the range [2**(n-1)+1, 2**n-1]'''
assert n > 1
return randrange(2 ** (n - 1) + 1, 2 ** n, 2)
# The first 50 prime numbers after 2

def get_lowlevel_prime(n):
"""Generate a prime candidate not divisible by first primes"""
while True:
# Obtain a random odd number
c = generate_n_bit_odd(n)

# Test divisibility by pre-generated primes
for divisor in first_50_primes:
if c % divisor == 0 and divisor ** 2 <= c:
break
else:
# The for loop did not encounter a break statement,
# so it passes low level primality test.
return c

def miller_rabin_primality_check(n, k=20):
'''Miller-Rabin Primality Test wwith specified round of test
Input:
n - n > 3, an odd integer to be tested for primality
k - the number of rounds of testing to perfor
Output:
True  - passed (n is a strong probable prime)
False - failed (n is a composite)'''

# For a given odd integer n > 3, write n as (2^s)*d+1,
# where s and d are positive integers and d is odd.
assert n > 3
if n % 2 == 0:
return False

s, d = 0, n - 1
while d % 2 == 0:
d >>= 1
s += 1

for _ in range(k):
a = randrange(2, n - 1)
x = pow(a, d, n)

if x == 1 or x == n - 1:
continue

for _ in range(s):
x = pow(x, 2, n)
if x == n - 1:
break
else:
# The for loop did not encounter a break statement,
# so it fails the test, it must be a composite
return False

# Passed the test, it is a strong probable prime
return True

def get_random_prime(num_bits):
while True:
pp = get_lowlevel_prime(num_bits)
if miller_rabin_primality_check(pp):
return pp

def gcd(a, b):
'''Computes the Great Common Divisor using the Euclid's algorithm'''
while b:
a, b = b, a % b
return a

def lcm(a, b):
"""Computes the Lowest Common Multiple using the GCD method."""
return a // gcd(a, b) * b

def exgcd(a, b):
"""Extended Euclidean Algorithm that can give back all gcd, s, t
such that they can make Bézout's identity: gcd(a,b) = a*s + b*t
Return: (gcd, s, t) as tuple"""
old_s, s = 1, 0
old_t, t = 0, 1
while b:
q = a // b
s, old_s = old_s - q * s, s
t, old_t = old_t - q * t, t
a, b = b, a % b
return a, old_s, old_t

def invmod(e, m):
"""Find out the modular multiplicative inverse x of the input integer
e with respect to the modulus m. Return the minimum positive x"""
g, x, y = exgcd(e, m)
assert g == 1

# Now we have e*x + m*y = g = 1, so e*x ≡ 1 (mod m).
# The modular multiplicative inverse of e is x.
if x < 0:
x += m
return x

def uint_from_bytes(xbytes: bytes) -> int:
"""This works only for unsigned (non-negative) integers."""
return int.from_bytes(xbytes, 'big')

def uint_to_bytes(x: int) -> bytes:
"""This works only for unsigned (non-negative) integers.
It does not work for 0."""
if x == 0:
return bytes(1)
return x.to_bytes((x.bit_length() + 7) // 8, 'big')

class RSA:
"""Implements the RSA public key encryption/decryption with default
exponent 65537 and default key size 2048"""

def __init__(self, key_length=RSA_DEFAULT_MODULUS_LEN,
exponent=RSA_DEFAULT_EXPONENT, fast_decrypt=False):
global privite_key
self.e = exponent
self.fast = fast_decrypt
t = 0
p = q = 2

while gcd(self.e, t) != 1:
p = get_random_prime(key_length // 2)
q = get_random_prime(key_length // 2)
t = lcm(p - 1, q - 1)

self.n = p * q
self.d = invmod(self.e, t)
privite_key = self.d
if (fast_decrypt):
self.p, self.q = p, q
self.d_P = self.d % (p - 1)
self.d_Q = self.d % (q - 1)
self.q_Inv = invmod(q, p)

# 加密函数 self.e self.n为公钥
def encrypt(self, binary_data: bytes):
int_data = uint_from_bytes(binary_data)
global public_key,N
public_key=self.e
N=self.n
return pow(int_data, self.e, self.n)

# 解密函数 self.d self.n为私钥
def decrypt(self, encrypted_int_data: int):
int_data = pow(encrypted_int_data, self.d, self.n)
return self.e

def generate_signature(self, encoded_msg_digest: bytes):
"""Use RSA private key to generate Digital Signature for given
encoded message digest"""
int_data = uint_from_bytes(encoded_msg_digest)
return pow(int_data, self.d, self.n)

def generate_signature_fast(self, encoded_msg_digest: bytes):
# Use Chinese Remaider Theorem + Fermat's Little Theorem to
# do fast RSA signature generation
assert self.fast == True
int_data = uint_from_bytes(encoded_msg_digest)
s1 = pow(int_data, self.d_P, self.p)
s2 = pow(int_data, self.d_Q, self.q)
t = s1 - s2
if t < 0:
t += self.p
h = (self.q_Inv * t) % self.p
s = (s2 + h * self.q) % self.n
return s

def decrypt_fast(self, encrypted_int_data: int):
# Use Chinese Remaider Theorem + Fermat's Little Theorem to
# do fast RSA description
assert self.fast == True
m1 = pow(encrypted_int_data, self.d_P, self.p)
m2 = pow(encrypted_int_data, self.d_Q, self.q)
t = m1 - m2
if t < 0:
t += self.p
h = (self.q_Inv * t) % self.p
m = (m2 + h * self.q) % self.n
return uint_to_bytes(m)

def verify_signature(self, digital_signature: int):
"""Use RSA public key to decrypt given Digital Signature"""
int_data = pow(digital_signature, self.e, self.n)
return uint_to_bytes(int_data)

# ---- Test RSA class ----
alice = RSA(512, 3, True)
msg = b'Textbook RSA in Python'
ctxt = alice.encrypt(msg)


P1.py
import threading
import socket
import time
from test_rsa import *
from pyDes import des, PAD_PKCS5, ECB

##在RSA中，P1需要公钥，需要RSA的加密函数
##在DES中，需要使用RSA对DES的秘钥进行加密然后再传过去，然后用DES加密算法对发送的消息进行加解密

address = ('127.0.0.1', 5005)  # 服务端地址和端口
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(address)  # 绑定服务端地址和端口
s.listen(5)
print('服务器已启动，等待客户端连接...')
conn, addr = s.accept()  # 返回客户端地址和一个新的 socket 连接 服务在这里处于阻塞状态
print('[+] Connected with', addr)
print('开始初始化...')

def send():
time.sleep(5)
print("请输入你的秘钥：")
key = input().replace(' ', '')
global GLO_KEY
GLO_KEY=key
key1=pow(int(key), int(public_key), int(N))
print("加密后的RSA",key1)
key1=str(key1)
#print('对秘钥进行加密',key1)
conn.sendall(key1.encode())
#conn.sendall(key.encode())
print("初始化结束，可以开始聊天 have fun!!!")
while True:
send = input('').encode()
if send=='我们结束吧'.encode():
break
conn.close()
des_obj = des(key, ECB, key, padmode=PAD_PKCS5)
secret_bytes = des_obj.encrypt(send)
#print("密文",secret_bytes)
#对数据进行加密
conn.sendall(secret_bytes)
conn.close()
s.close()

def my():
global public_key,N
public_key=conn.recv(1024)
public_key=public_key.decode()
print("收到对方的public_key",public_key)
N=conn.recv(1024)
N=N.decode()
print("收到对方的N",N)
while True:
data = conn.recv(1024)
# 对数据进行解密
des_obj = des(str(GLO_KEY), ECB, str(GLO_KEY), padmode=PAD_PKCS5)
data = des_obj.decrypt(data)
print('', data.decode())

if __name__ == '__main__':
#服务器部分
p = threading.Thread(target=my)
p.start()
send()

P2.py
import threading
import socket
import time
import sys
from test_rsa import *
from pyDes import des, PAD_PKCS5, ECB

##在RSA中，P2需要私钥，需要RSA的解密函数
##在DES中，需要DES的加密解密函数

address = ('127.0.0.1', 5005)  # 服务端地址和端口
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("客户端已启动")
try:
s.connect(address)  # 尝试连接服务端
except Exception:
print('[!] Server not found ot not open')
sys.exit()

def send():
msg_key=str(public_key)
msg_n=str(N)
s.sendall(msg_key.encode())
time.sleep(2)
s.sendall(msg_n.encode())
while True:
send = input('').encode()
if send == '我们结束吧'.encode():  # 自定义结束字符串
break
des_obj = des(str(GLO_KEY), ECB, str(GLO_KEY), padmode=PAD_PKCS5)
secret_bytes = des_obj.encrypt(send)
s.sendall(secret_bytes)
s.close()

def my():
print("正在等待服务器发送秘钥...")
global DES_KEY
DES_KEY = s.recv(1024)
DES_KEY = DES_KEY.decode()
DES_KEY = pow(int(DES_KEY),int(privite_key),int(N))
#print('收到的秘钥：', DES_KEY)
global GLO_KEY
GLO_KEY=DES_KEY
print("已收到发来的秘钥，可以开始聊天 have fun!!!")
while True:
data = s.recv(1024)
#对数据进行解密
des_obj = des(str(DES_KEY), ECB, str(DES_KEY), padmode=PAD_PKCS5)
data = des_obj.decrypt(data)
print('', data.decode())

if __name__ == '__main__':
p = threading.Thread(target=my)
p.start()
send()


三、运行结果
P1为服务器，也就是图中发方，P2为客户端，相当于图中收方，但是他们之间是能够进行全双工通信的，不是一个只能收，一个只能发。
1.首先启动服务器，等待客户端连接

2.启动客户端，等待服务器发送DES秘钥

3.这时的服务器受到了客户端发来的公钥 和 大整数N

4.服务器将用这些对自己的DES秘钥进行加密
这里需要注意的是DES秘钥长度固定为64bit，也就是8个字符，在输入时需要注意。

按回车，就可以通信啦

测试汉字：

测试字符串：
P1:

p2:

总结
一开始想直接用Python中的DES包和RSA包直接对数据进行加密，奈何格式不是很匹配，变换格式有些许麻烦，索性直接创建了两个Python文件来进行DES和RSA加密。


展开全文
• 自己的课程报告，用vb编写的一个程序，包括DES和RSA算法的实现过程，还有一个简单的加密时间对比。另外还有一个设计报告的文档，里面有使用详细过程和截图。
• DES加密软件，采用DES算法，可以对任意文档或者字符串进行加密解密。 各种加密算法的源代码，包括DES，RSA，DAS，RC4,RC5等 包括1次DES，2次DES和3次DES。 除了算法，其他都原创。直接运行。
• 今天跟第三方公司对接别人看了我写的文档当时文档写的是DES加密，然后我的一个回答都让我觉得对不起别人，我说了是AES加密，当时AES和RSA加解密的原理我不了解导致我也误解了别人，今天就特意去理解了一下，下面就看...
今天跟第三方公司对接别人看了我写的文档当时文档写的是DES加密，然后我的一个回答都让我觉得对不起别人，我说了是AES加密，当时AES和RSA加解密的原理我不了解导致我也误解了别人，今天就特意去理解了一下，下面就看一下RSA非对称的加解密吧

首先先来说一下RSA和AES的区别吧

RSA

非对称加密，公钥加密，私钥解密，反之亦然。由于需要大数的乘幂求模等算法，运行速度慢，不易于硬件实现。

通常私钥长度有512bit，1024bit，2048bit，4096bit，长度越长，越安全，但是生成密钥越慢，加解密也越耗时。

既然是加密，那肯定是不希望别人知道我的消息，所以只有我才能解密，所以可得出公钥负责加密，私钥负责解密；

同理，既然是签名，那肯定是不希望有人冒充我发消息，只有我才能发布这个签名，所以可得出私钥负责签名，公钥负责验证。

AES

对称加密，密钥最长只有256个bit，执行速度快，易于硬件实现。由于是对称加密，密钥需要在传输前通讯双方获知。

基于以上特点，通常使用RSA来首先传输AES的密钥给对方，然后再使用AES来进行加密通讯。

好啦说完区别就来看一下RSA如何实现加解密的吧

第一步需要去：http://web.chacuo.net/netrsakeypair  这里生成两队公私钥，我用的是2048位（bit），PKCS#8的格式生成公私钥，我把公私钥放到了一个文件里面所以，下面的代码就是RSA的加密代码：

好啦上面就是RSA的加密啦

下面来看一下RSA的解密的代码吧！

好啦这些就是RSA的加解密的代码啦！！！


展开全文
• 利用rsa公钥，使用rsa算法加密这个密钥‘12345’，并把它放在要加密的数据的前面（可能后面跟着一个分割符或文件长度，以区分数据密钥），然后，使用对称加密算法加密正文，使用的密钥就是‘12345’。当对方收到时...
• 包括RSA,DSA, AES, DES, 3DES blowfish 等等. 因为要实现ssh协议, 所以用到了这些算法, 这些算法在macios上的接口比较难用(这里不提 openssl 在 apple 上的接口了)原作者主要参考了apple的文档: ...
Mac 和 iOS 上使用到的对称和非对称加密算法. 包括RSA,DSA, AES, DES, 3DES 和 blowfish 等等.
因为要实现ssh协议, 所以用到了这些算法, 这些算法在mac和ios上的接口比较难用(这里不提 openssl 在 apple 上的接口了)

原作者主要参考了apple的文档:

Cryptographic Services Guide
Apple Encrypting and Hashing Data

先大致概括一下整体情况:

基本上这两个平台上的加密解密都和keychain service 密不可分. keychain是mac和ios上用来保存证书,密码,key 等等敏感信息的存储区. 有专门的api访问这些接口. 有时候我们为了获得一个 key 的实例,必须想办法把数据导入到keychain中,然后才能通过keychain获得一个key的实例.

在mac 上, 有三个方式实现加密解密签名服务:

Security Transforms API —a Core-Foundation-level API that provides support for signing and verifying,  symmetric cryptography, andBase64 encoding and decoding.
是 CoreFoundation 级别的api, 提供了, 最全的功能和算法支持. 包括对称,非对称算法. 实现加密,签名功能. 但遗憾的是这个接口只在mac上有效. iOS上没有. 但有些功能必须要用到, 所以要实现跨平台的代码,需要一些补丁.
Common Crypto—a C-level API that can perform most symmetric encryption and decryption tasks
这是一个 C 风格的接口. 好消息是它在mac和ios上都有, 可以跨平台. 但坏消息是, 它只包含了, 对称加密算法, 却没有非对称算法. 因此只能加密解密,而不能签名和验证. 其实之前 Apple上还有一个 ComonCryptoRSA 模块, 但后来不知为何消失了.
CDSA/CSSM —a legacy API that should be used only to perform tasks not supported by the other two APIs, such as asymmetric encryption
这个名字比较吓人, Common Data Security Architecture (CDSA) 通用数据安全架构. 很奇怪,它被apple接受后不久, 就被废弃了. 现在已经不建议使用了. 所以就不提它了.
在 iOS 上, 基本上有两种方式:

Common Crypto. 这个在上面已经说过了. 对称算法接口.
使用系统提供的特有api实现加密,解密, 签名和验证:

系统提供了下面4个函数:

SecKeyEncrypt—encrypts a block of data using the specified key.

SecKeyDecrypt—decrypts a block of data using the specified key.

SecKeyRawSign—signs a block of data using the specified key.

SecKeyRawVerify—verifies a signature against a block of data and a specified key.

基于上面的分析, 我们秉着尽可能减少代码重复, 跨平台开发的原则: 对称算法就使用 “Common Crypto” 模块了. 因为两个平台都有. 而非对称则需要分别实现了.

详细分享一些细节:

一, 非对称加密算法, 签名和验证.(RSA/DSA signature and verity)

这需要在两个平台独立开发.

Mac 平台.

在 mac 平台上, 我们使用它的 Security Transforms API.

参考这里: Security Transforms Programming Guide-Signing and Verifying

上面有很好的 代码 片段. 需要注意的是如何把 RSA 的参数 变成 api 需要的 SecKeyRef 对象.

这是它的导入片段.

params.keyUsage = NULL;
params.keyAttributes = NULL;

SecExternalItemType itemType = kSecItemTypeCertificate;
SecExternalFormat externalFormat = kSecFormatPEMSequence;
int flags = 0;

oserr = SecItemImport(cfdataprivatekey,
NULL, // filename or extension
&externalFormat, // See SecExternalFormat for details
&itemType, // item type
flags, // See SecItemImportExportFlags for details
&params,
NULL, // Don't import into a keychain
&temparray);
if (oserr) {
fprintf(stderr, "SecItemImport failed (oserr=%d)\n", oserr);
CFShow(temparray);
exit(-1);
}

privatekey = (SecKeyRef)CFArrayGetValueAtIndex(temparray, 0);


这里是为了创建SecKeyRef实例. 通过 SecItemImport 把数据导入.变成SecKeyRef实例. 数据放在cfdataprivatekey 中. 这个数据必须是 Pem格式的证书. 因为这个case下需要私钥, 所以这个证书需要包含私钥, 都是pem格式.

这里特别介绍一下, 如何从ssh 的公钥格式导入. 以RSA为例, RSA的公钥其实是一个底数e, 和一个大整数 m ,

e = [int32(len), bytes(value)]
m = [int32(len), bytes(value)]

e 和 m 的结构一样. 先是4个字节的长度, 然后紧跟上字节序列. len是 大端在前的, 跟通常的小端是有区别的.
完整的机构大概是这个样子的:

Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-rsa', e, m]

keydata = 'ssh-rsa' + Base64Encode(Binary)

这个keydata 就可以用来构建上面用到的参数cfdataprivatekey了.

对于DSA, 结构跟上面类似:

p = [int32(len), bytes(value)]
q = [int32(len), bytes(value)]
g = [int32(len), bytes(value)]
y = [int32(len), bytes(value)]

Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-dss', p, q, g, y]

keydata = 'ssh-dss' + Base64Encode(Binary)

对于 iOS, 平台, 我们使用上面说的两个函数来签名和验证:

SecKeyRawSign—signs a block of data using the specified key.

SecKeyRawVerify—verifies a signature against a block of data and a specified key.
这两个函数要命的是都需要一个 SecKeyRef 参数, iOS 上还真没有直接的方式可以通过大整数直接创建 SecKeyRef的实例.

要么通过 keychain 读取. 或者通过 SecPKCS12Import() 函数导入 pkcs12 格式的包含私钥的证书, 然后获得 SecIdentityRef 实例. 然后再通过 SecIdentityCopyPrivateKey() 函数把其中的 私钥导出成 SecKeyRef实例.

OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data,
SecIdentityRef *outIdentity,
SecTrustRef *outTrust,
CFStringRef keyPassword)
{
OSStatus securityError = errSecSuccess;

const void *keys[] =   { kSecImportExportPassphrase };
const void *values[] = { keyPassword };
CFDictionaryRef optionsDictionary = NULL;

/* Create a dictionary containing the passphrase if one
was specified.  Otherwise, create an empty dictionary. */
optionsDictionary = CFDictionaryCreate(
NULL, keys,
values, (keyPassword ? 1 : 0),
NULL, NULL);  // 1

CFArrayRef items = NULL;
securityError = SecPKCS12Import(inPKCS12Data,
optionsDictionary,
&items);                    // 2

//
if (securityError == 0) {                                   // 3
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,
kSecImportItemIdentity);
CFRetain(tempIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);

CFRetain(tempTrust);
*outTrust = (SecTrustRef)tempTrust;
}

if (optionsDictionary)                                      // 4
CFRelease(optionsDictionary);

if (items)
CFRelease(items);

return securityError;
}

另外一个方法是, 苹果官方给的示例代码, 强制拼凑 SecKeyRef示例.
这里有 SecKeyWrapper 的实例代码: SecKeyWrapper 的实例代码

并且可以在这里直接下载到 源码: SecKeyWrapper 源码

这个源码里面有很多 苹果写的例子. 非常好. 对剑使用这里面的代码实现

二, 对于对称加密算法.

这个比较简单了, 我们直接使用 Common Crypto 模块. 在mac 和ios上可以跨平台.

请参考这里: Apple Common Crypto library

使用 CCCryptorCreate 或者 CCCryptorCreateWithMode 创建 CCCryptorRef 对象.
然后不断的调用 CCCryptorUpdate. 进行加密/解密.
最后调用:CCCryptorFinal. 获取最后一块加密方法.
建议使用 CCCryptorCreateWithMode 方法.因为它能指定更多的参数. 比如 加密算法的padding 和ciphermode.

最后再顺便分享一下Mac 和iOS上生成 密码学安全的随机数的方法: Generating Random Numbers

简单的来说. 在mac上, 可以通过 fopen 读取 /dev/random 设备获得密码学安全的随机数.

FILE *fp = fopen("/dev/random", "r");

if (!fp) {
perror("randgetter");
exit(-1);
}

uint64_t value = 0;
int i;
for (i=0; i<sizeof(value); i++) {
value <<= 8;
value |= fgetc(fp);
}

fclose(fp);

而在 iOS 上, 由于不能读取设备, 它提供了 专门的 方法: SecRandomCopyBytes , 用起来非常简单.

代码阶段(AES对称加密)

@class NSString;

@interface NSData (Encryption)

- (NSData *)AES256ParmEncryptWithKey:(NSString *)key;   //加密
- (NSData *)AES256ParmDecryptWithKey:(NSString *)key;   //解密

@end  

#import "Encryption.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (Encryption)

- (NSData *)AES256ParmEncryptWithKey:(NSString *)key   //加密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
voidvoid *buffer = malloc(bufferSize);
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}

- (NSData *)AES256ParmDecryptWithKey:(NSString *)key   //解密
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
voidvoid *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeAES128,
NULL,
[self bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}  

转载:
1. http://www.cnblogs.com/shuidao/p/4392312.html
2.  http://blog.csdn.net/showhilllee/article/details/2959724
展开全文
• 包括RSA,DSA, AES, DES, 3DES blowfish 等等.因为要实现ssh协议, 所以用到了这些算法, 这些算法在macios上的接口比较难用, 我在这折腾了好长时间, 这里分享出来, 希望对大家有帮助.(这里不提 openssl 在 apple...
分享在Mac 和 iOS 上使用到的对称和非对称加密算法. 包括RSA,DSA, AES, DES, 3DES 和 blowfish 等等.因为要实现ssh协议, 所以用到了这些算法, 这些算法在mac和ios上的接口比较难用, 我在这折腾了好长时间, 这里分享出来, 希望对大家有帮助.(这里不提 openssl 在 apple 上的接口了)
主要参考了apple的文档:
Cryptographic Services Guide
Apple Encrypting and Hashing Data
先大致概括一下整体情况:基本上这两个平台上的加密解密都和 keychain service 密不可分. keychain是mac和ios上用来保存证书,密码,key 等等敏感信息的存储区. 有专门的api访问这些接口. 有时候我们为了获得一个 key 的实例,必须想办法把数据导入到keychain中,然后才能通过keychain获得一个key的实例. 后面再说.
在mac 上, 有三个方式实现加密解密签名服务:

Security Transforms API —a Core-Foundation-level API that provides support for signing and verifying, symmetric cryptography, and Base64 encoding and decoding.是 CoreFoundation 级别的api, 提供了, 最全的功能和算法支持. 包括对称,非对称算法. 实现加密,签名功能. 但遗憾的是这个接口只在mac上有效. iOS上没有. 但有些功能必须要用到, 所以要实现跨平台的代码,需要一些补丁.

Common Crypto—a C-level API that can perform most symmetric encryption and decryption tasks这是一个 C 风格的接口. 好消息是它在mac和ios上都有, 可以跨平台. 但坏消息是, 它只包含了, 对称加密算法, 却没有非对称算法. 因此只能加密解密,而不能签名和验证. 其实之前 Apple上还有一个 ComonCryptoRSA 模块, 但后来不知为何消失了.

CDSA/CSSM —a legacy API that should be used only to perform tasks not supported by the other two APIs, such as asymmetric encryption这个名字比较吓人, Common Data Security Architecture (CDSA) 通用数据安全架构. 很奇怪,它被apple接受后不久, 就被废弃了. 现在已经不建议使用了. 所以就不提它了.

在 iOS 上, 基本上有两种方式:

Common Crypto. 这个在上面已经说过了. 对称算法接口.

使用系统提供的特有api实现加密,解密, 签名和验证:

系统提供了下面4个函数:
SecKeyEncrypt—encrypts a block of data using the specified key.

SecKeyDecrypt—decrypts a block of data using the specified key.

SecKeyRawSign—signs a block of data using the specified key.

SecKeyRawVerify—verifies a signature against a block of data and a specified key.


基于上面的分析, 我们秉着尽可能减少代码重复, 跨平台开发的原则: 对称算法就使用 “Common Crypto” 模块了. 因为两个平台都有. 而非对称则需要分别实现了.
下面详细分享一些细节:
一, 非对称加密算法, 签名和验证.(RSA/DSA signature and verity)
这需要在两个平台独立开发.
Mac 平台.
在 mac 平台上, 我们使用它的 Security Transforms API.
参考这里: Security Transforms Programming Guide-Signing and Verifying
上面有很好的 代码 片段. 需要注意的是如何把 RSA 的参数 变成 api 需要的 SecKeyRef 对象.
这是它的导入片段.
    params.keyUsage = NULL;
params.keyAttributes = NULL;

SecExternalItemType itemType = kSecItemTypeCertificate;
SecExternalFormat externalFormat = kSecFormatPEMSequence;
int flags = 0;

oserr = SecItemImport(cfdataprivatekey,
NULL, // filename or extension
&externalFormat, // See SecExternalFormat for details
&itemType, // item type
flags, // See SecItemImportExportFlags for details
&params,
NULL, // Don't import into a keychain
&temparray);
if (oserr) {
fprintf(stderr, "SecItemImport failed (oserr=%d)\n", oserr);
CFShow(temparray);
exit(-1);
}

privatekey = (SecKeyRef)CFArrayGetValueAtIndex(temparray, 0);

这里是为了创建 SecKeyRef 实例. 通过 SecItemImport 把数据导入.变成SecKeyRef实例. 数据放在 cfdataprivatekey 中. 这个数据必须是 Pem格式的证书. 因为这个case下需要私钥, 所以这个证书需要包含私钥, 都是pem格式.
这里特别介绍一下, 如何从ssh 的公钥格式导入. 以RSA为例, RSA的公钥其实是一个底数e, 和一个大整数 m ,
e = [int32(len), bytes(value)]
m = [int32(len), bytes(value)]

e 和 m 的结构一样. 先是4个字节的长度, 然后紧跟上字节序列. len是 大端在前的, 跟通常的小端是有区别的.完整的机构大概是这个样子的:
Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-rsa', e, m]

keydata = 'ssh-rsa' + Base64Encode(Binary)


这个keydata 就可以用来构建上面用到的参数cfdataprivatekey了.
对于DSA, 结构跟上面类似:
p = [int32(len), bytes(value)]
q = [int32(len), bytes(value)]
g = [int32(len), bytes(value)]
y = [int32(len), bytes(value)]

Binary = [0x00, 0x00, 0x00, 0x07, 'ssh-dss', p, q, g, y]

keydata = 'ssh-dss' + Base64Encode(Binary)


对于 iOS, 平台, 我们使用上面说的两个函数来签名和验证:
SecKeyRawSign—signs a block of data using the specified key.

SecKeyRawVerify—verifies a signature against a block of data and a specified key.

这两个函数要命的是都需要一个 SecKeyRef 参数, iOS 上还真没有直接的方式可以通过大整数直接创建 SecKeyRef的实例.
要么通过 keychain 读取. 或者通过 SecPKCS12Import() 函数导入 pkcs12 格式的包含私钥的证书, 然后获得 SecIdentityRef 实例. 然后再通过 SecIdentityCopyPrivateKey() 函数把其中的 私钥导出成 SecKeyRef实例.
OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data,
SecIdentityRef *outIdentity,
SecTrustRef *outTrust,
CFStringRef keyPassword)
{
OSStatus securityError = errSecSuccess;

const void *keys[] =   { kSecImportExportPassphrase };
const void *values[] = { keyPassword };
CFDictionaryRef optionsDictionary = NULL;

/* Create a dictionary containing the passphrase if one
was specified.  Otherwise, create an empty dictionary. */
optionsDictionary = CFDictionaryCreate(
NULL, keys,
values, (keyPassword ? 1 : 0),
NULL, NULL);  // 1

CFArrayRef items = NULL;
securityError = SecPKCS12Import(inPKCS12Data,
optionsDictionary,
&items);                    // 2

//
if (securityError == 0) {                                   // 3
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust,
kSecImportItemIdentity);
CFRetain(tempIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);

CFRetain(tempTrust);
*outTrust = (SecTrustRef)tempTrust;
}

if (optionsDictionary)                                      // 4
CFRelease(optionsDictionary);

if (items)
CFRelease(items);

return securityError;
}

另外一个方法是, 苹果官方给的示例代码, 强制拼凑 SecKeyRef示例.这里有 SecKeyWrapper 的实例代码: SecKeyWrapper 的实例代码
并且可以在这里直接下载到 源码: SecKeyWrapper 源码
这个源码里面有很多 苹果写的例子. 非常好. 对剑使用这里面的代码实现.
二, 对于对称加密算法.这个比较简单了, 我们直接使用 Common Crypto 模块. 在mac 和ios上可以跨平台.
请参考这里: Apple Common Crypto library
使用 CCCryptorCreate 或者 CCCryptorCreateWithMode 创建 CCCryptorRef 对象.然后不断的调用 CCCryptorUpdate. 进行加密/解密.最后调用:CCCryptorFinal. 获取最后一块加密方法.

建议使用 CCCryptorCreateWithMode 方法.因为它能指定更多的参数. 比如 加密算法的padding 和ciphermode.
最后再顺便分享一下Mac 和iOS上生成 密码学安全的随机数的方法: Generating Random Numbers
简单的来说. 在mac上, 可以通过 fopen 读取 /dev/random 设备获得密码学安全的随机数.
FILE *fp = fopen("/dev/random", "r");

if (!fp) {
perror("randgetter");
exit(-1);
}

uint64_t value = 0;
int i;
for (i=0; i<sizeof(value); i++) {
value <<= 8;
value |= fgetc(fp);
}

fclose(fp);


而在 iOS 上, 由于不能读取设备, 它提供了 专门的 方法: SecRandomCopyBytes , 用起来非常简单.
欢迎访问我的独立博客 https://blog.byneil.com
转载于:https://www.cnblogs.com/shuidao/p/4392312.html
展开全文
• Java实现文件的RSA和DES加密算法 一、 基础知识 根据密钥类型不同将现代密码技术分为两类：对称加密算法（秘密钥匙加密非对称加密算法（公开密钥加密）。 对称钥匙加密系统是加密和解密均采用同一把秘密钥匙...
• 在笔试或面试中，经常会问到对称加密算法和非对称加密算法区别，哪些方式属于对称加密，哪些属于非对称加密，哪些地方用到了加密。 下面罗列出几种使用加密解密的场景~ 系统中前后端交互的敏感字符加密，例如身份证...
• 加密技术是利用数学或物理...常用的加密算法有DES系列（包括DES和3DES），RC系列(常用的有RC4和RC6)和AES等对称加密算法加密密钥和解密密钥相同或相似）以及RSA等非对称加密算法。除此此外，还有用于获取信息摘要的M
• OpenSSL 转换证书格式 数字安全证书(CA证书)介绍 CA证书应用一：Outlook发送邮件时，为邮件添加数字签名 CA证书应用二：制作带数字签名的PDF文档 ... CA证书应用三：给Word...用实例讲解RSA加密算法(精) ...
• 参考文档：https://blog.csdn.net/u011068702/article/details/73357150对称加密（数据保密性） 算法DES 、 3DES 、 RC5、AES 特点：加密和解密使用相同的密钥  加密原文非对称加密（数据保密性） 算法：DH、RSA ...
• MD5 \ SHA \ DES \ 3DES \ RC2RC4 \ RSA \ IDEA \ DSA \ AES 3.加密算法的选择 一般公司都会有一套自己的加密方案，按照公司接口文档的规定去加密   二、MD5 1.简单说明 MD5:全称是Message Digest Alg
• RFC2313 PKCS#1：RSA加密 版本1.5 RFC2330 IP 执行规则的管理 RFC2343 应用于捆绑的MPEG的RTP有效载荷的格式 RFC2344 移动IP反向隧道 RFC2349 TFTP 休息间隔传输大小选项 RFC2367 PF_KEY键管理 API,版本 2 RFC...
• 数字签名 DSS/SHA-1、RSA/MD5 采用SHA-1或MD5消息摘要算法计算消息的摘要值（散列码），用发送者的私钥按DSS或RSA算法加密消息摘要 压缩 PKZIP 消息在传送存储时可使用PKZIP压缩 E-mail兼容性 Radix-64 对E-mail...
• 本工程是东南大学网络空间学院黄杰老师课堂大作业，需要完成对称加密算法DES、AES，Hash算法SHA-1MD5，非对称加密RSA,具体要求见. 工程目录 . +-- README.md % 当前文档 +-- LICENCE +-- SecurityAlgs | +-- ....
• 一.简单说明 ...MD5\SHA\DES\3DES\RC2RC4\RSA\IDEA\DSA\AES3.加密算法的选择 一般公司都会有一套自己的加密方案，按照公司接口文档的规定加密二.MD5 1.简单说明 MD5:全称是Message Digest Algo
• 一面： 1、 介绍你了解的Hadoop。 我谈到了HDFS的一些机制（块大小为64MB，副本为3个（据说通过数学...DES（对称密钥加密），RSA（非对称密钥加密），MD5 4、 linux命令 如何查看命令的帮助文档：本地man，在...
• ## openssl-1.0.0a

热门讨论 2010-06-19 12:33:49
OpenSSL一共实现了4种非对称加密算法，包括DH算法、RSA算法、DSA算法椭圆曲线算法（EC）。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换，也可以用于数字签名，当然，如果你能够忍受其缓慢的速度，那么也...
• 用Java加密类实现DESRSA及SHA的加密算法.rar 用jdom解析xml.rar 网上书店.rar 网络电视源代码TV-Browser.rar 网络蚂蚁Java版.rar 网页浏览器.rar 蜀山剑侠传游戏J2ME手机版源代码.rar 轻松商城系统.rar 选修课程...
• ## OpenSSL-1_0_0d_Win32

热门讨论 2011-04-13 17:57:46
非对称加密算法 OpenSSL一共实现了4种非对称加密算法，包括DH算法、RSA算法、DSA算法椭圆曲线算法（EC）。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换，也可以用于数字签名，当然，如果你能够忍受其缓慢的...
• 买要商家家支验利用付证信客哈希息户算订数字法货信摘生要连买接家起利来用，再（利用哈希算法生成双重数字摘要。 2 ）对双重数字摘要加密生成双重数字签名，将（ 3 ）、（ 4 ）（ 5 发送给商家，商家收到信息后...
• 用Java加密类实现DESRSA及SHA的加密算法.rar 用jdom解析xml.rar 电子书店管理系统.rar 编译原理--LR（1）分析表构造（JAVA）.rar 网上书店.rar 网络电视源代码TV-Browser.rar 网络蚂蚁Java版.rar 网页浏览器.rar ...
• luaMVC 框架(xlua+pureMVC) 更新说明 LuaMVC Beta 0.1版本更新说明 ...RSA加密与解密 完善框架配置问题 完善ViewMaster其余接口 修复部分由框架引起的bug 完善发布前后路径调试繁琐的问题
• 8.1.6　实例：DES算法加密解密演示 123 8.2　国际数据加密算法（IDEA） 131 8.2.1　算法描述 131 8.2.2　生成子密钥 133 8.2.3　实例：IDEA算法加密解密演示 134 8.3　Blowfish算法 139 8.3.1　算法描述 139 8.3.2　...
• 8.1.6　实例：DES算法加密解密演示 123 8.2　国际数据加密算法（IDEA） 131 8.2.1　算法描述 131 8.2.2　生成子密钥 133 8.2.3　实例：IDEA算法加密解密演示 134 8.3　Blowfish算法 139 8.3.1　算法描述 139 8.3.2　...
• ## java源码包---java 源码 大量 实例

千次下载 热门讨论 2013-04-18 23:15:26
Java非对称加密源程序代码实例，本例中使用RSA加密技术，定义加密算法可用 DES,DESede,Blowfish等。 　设定字符串为“张三，你好，我是李四” 　产生张三的密钥对(keyPairZhang) 　张三生成公钥(publicKeyZhang...
• ## java源码包2

千次下载 热门讨论 2013-04-20 11:28:17
Java非对称加密源程序代码实例，本例中使用RSA加密技术，定义加密算法可用 DES,DESede,Blowfish等。 　设定字符串为“张三，你好，我是李四” 　产生张三的密钥对(keyPairZhang) 　张三生成公钥(publicKeyZhang...
• ## java源码包3

千次下载 热门讨论 2013-04-20 11:30:13
Java非对称加密源程序代码实例，本例中使用RSA加密技术，定义加密算法可用 DES,DESede,Blowfish等。 　设定字符串为“张三，你好，我是李四” 　产生张三的密钥对(keyPairZhang) 　张三生成公钥(publicKeyZhang...