您的位置:首页 > 编程语言 > Python开发

现代密码学 实验

2015-12-21 21:39 896 查看
学了一门课 ,叫《现代密码学》,做实验要实现AES加密文件,RSA加密AES秘钥,然后再反向解密出来,模拟的过程如下:

Alice先加密!

加密过程:



之后Bob再解密!

解密过程:



鉴于是个学渣,用到的RSA,AES,MD5算法都只是大概了解一下,并没有花心思去实现,而且密码学老师给的密码库并不会用,所以,在另外一位同学的建议下,用了只是知道一点点的python来实现,因为有两个挺好的密码库来用  pycrypto  M2crypto

过程很曲折,轻易勿模仿!

之后是实验报告

实验报告

 

 

一、     设计思路

加密:

Alice拥有: AES秘钥,Bob公钥,Alice的私钥

解密:

Bob拥有:Alice的公钥,Bob的私钥

 

二、     程序结构

采用python编写,用到两个加解密库:pycrypto,M2crypto

main.py     主函数,调用其他函数

functions.py   具体函数的实现

 

三、     函数代码

①  # AES加密

def aes_encrypt(aes_file, key,iv):  #aes_file 文件,key 16-bytes 对称秘钥

    from Crypto.Cipher import AES

    from Crypto import Random

    cipher = AES.new(key, AES.MODE_OFB,iv)   # 生成了加密时需要的实际密码,这里采用OFB模式

    # if fs is a multiple of 16

    x = len(aes_file) % 16

    print '要加密文件的长度是: ', len(aes_file)

    print '需要填充的数据长度 : ',(16- x)%16

    if x != 0:

        aes_file_pad = aes_file + '0'*(16 - x)# It should be 16-x

    else:

        aes_file_pad=aes_file

    msg = cipher.encrypt(aes_file_pad)

    return msg,(16- x)%16

 

②  # AES解密

def aes_decrypt(aes_file, key,iv):

    from Crypto.Cipher import AES

    cipher = AES.new(key, AES.MODE_OFB,iv)   # 生成了解密时需要的实际密码,这里采用OFB模式

    msg=cipher.decrypt(aes_file)

    return msg

 

③# 计算MD5值

def md5_encrypt(md5_file):

    from Crypto.Hash import MD5

    msg = MD5.new()

    msg.update(md5_file)

    return msg.hexdigest()

 

④# RSA私钥加密

def rsa_private_encrypt(msg,file_rsa_private_key_name):

    from M2Crypto import RSA    # 用M2Crypto下的RSA模块

    rsa_private_key=RSA.load_key(file_rsa_private_key_name)

    msg_encrypted=rsa_private_key.private_encrypt(msg,RSA.pkcs1_padding)

    return msg_encrypted

 

RSA公钥加密、私钥解密、公钥解密与此类似

 

 

四、     问题解决

1.     采用AES加密CFB(输出反馈模式),需要初始化加密模块,生成16位的iv,需要给Bob发送,可以跟AES秘钥一样采用RSA加密

 

2. 读入字符串时,区别raw_input(),input(),只能用前者

  原因:input会把输入的字符串当做一个变量名

 

3.AES加密时遇到数据块不足一整块情况,会进行填充,这样导致内容发生变化,以致解密出的文件与原文件MD5不一致,故需把填充位数发送给Bob,解密时可去掉填充部分

 

 

 

五、     参考网页

基本python语法:(这网站挺好的)

http://www.runoob.com/python/python-tutorial.html

关于命令行显示:http://jingyan.baidu.com/article/925f8cb8e00554c0dde0562b.html

pycrypto库说明:(MD5例子在此找到)

https://pythonhosted.org/pycrypto/

M2crypto库说明:

http://www.heikkitoivonen.net/m2crypto/api/

实现AES:

http://blog.chinaunix.net/uid-26275986-id-4349364.html

实现RSA:

http://my.oschina.net/kuaikuai/blog/208075?fromerr=rMpqv2p4

生成RSA公钥秘钥:

http://codego.net/438504/

 

环境配置(建议自己用virtualenv配置一个虚拟python环境):

Python安装:

http://jingyan.baidu.com/article/7908e85c78c743af491ad261.html

或者http://www.runoob.com/python/python-install.html

 

 两个库安装(直接使用pip):

pip install pycrypto

pip install --egg M2CryptoWin32

再之后是乱乱的代码

 

main.py

# coding:utf8

import functions
from functions import file_encrypt, file_decrypt, printCN, raw_inputCN

while 1:                                             # 相当于主程序了。。。
    printCN("这是一个加解密文件程序,请按照提示输入!\n")
    printCN("请选择:\n1.加密文件  2.解密文件 3.退出")
    select = input()
    if select == 1:
        file_encrypt()
        break
    elif select == 2:
        file_decrypt()
        break
    else:
        break


functions.py

# coding:utf8

# 终端输出中文不乱码
def printCN(str1):
    print(str1.decode("utf8"))

def raw_inputCN(str1):
    return raw_input(str1.decode("utf8").encode("gbk"))

def file_encrypt():
    printCN("请把以下文件放在与此程序同一路径下")
    printCN("1.要加密的文件")
    printCN("2.AES秘钥文件")
    printCN("3.你的RSA私钥文件")
    printCN("4.接收者的RSA公钥文件")
    raw_inputCN("放好之后,回车继续\n")
    file_name=raw_inputCN("请输入要加密的文件名:\n")
    file_aes_key_name=raw_inputCN("请输入AES秘钥文件名:\n")

    file=open(file_name,'rb')       # 打开要加密文件
    file_msg=file.read()
    file_aes_key=open(file_aes_key_name,'rb')   # 打开AES秘钥文件
    aes_key=file_aes_key.read()

    from Crypto.Cipher import AES
    from Crypto import Random
    # iv用来记录AES随机生成的一个16字节初始向量
    iv = Random.new().read(AES.block_size)   # 使用Crypto中Random模块,读取16字节数据作为iv的值,AES分块大小固定为16字节
    printCN("开始对原文件进行AES加密......")
    file_encrypted_msg,fill_number=aes_encrypt(file_msg,aes_key,iv)  # 调用AES加密函数  fill_number填充的位数
    file_encrypted=open('file_encrypted','wb')    # 生成存储加密后文件
    file_encrypted.write(file_encrypted_msg)
    file_encrypted.close()
    printCN("原文件AES加密完成!")
    file_fill_number=open('fill_number','wb')     # 生成存储填充位数文件
    file_fill_number.write(str(fill_number))
    file_fill_number.close()

    printCN("开始对原文件进行MD5摘要")
    md5_msg=md5_encrypt(file_msg)
    printCN("MD5摘要完成!")
    file.close()                           # 已不用原文件,关闭

    file_rsa_private_name=raw_inputCN("请输入你的RSA私钥文件名:\n")
    printCN("开始对MD5摘要签名")
    signature_msg=rsa_private_encrypt(md5_msg,file_rsa_private_name)  # MD5摘要RSA加密
    printCN("MD5摘要签名完成!")
    printCN("对签名进行AES加密")         # 因为MD5值是32位的,所以AES16位一块的加密不需要填充数据
    signature_encrypted_msg,number=aes_encrypt(signature_msg,aes_key,iv)   # number仅用来接收一个值,没有其他作用
    file_signature_encrypted=open('file_signature_encrypted','wb')    # 生成存储加密后的签名文件
    file_signature_encrypted.write(signature_encrypted_msg)
    file_signature_encrypted.close()
    printCN("签名AES加密完成!")

    file_receiver_rsa_public_name=raw_inputCN("请输入接收者RSA公钥文件名:\n")
    printCN("开始对AES秘钥进行RSA加密")
    aes_key_encrypted=rsa_public_encrypt(aes_key,file_receiver_rsa_public_name)
    file_aes_key_encrypted=open('AES_key_encrypted','wb')
    file_aes_key_encrypted.write(aes_key_encrypted)
    file_aes_key_encrypted.close()
    printCN("AES秘钥RSA加密完成!")
    printCN("开始对iv进行RSA加密")
    iv_encrypted=rsa_public_encrypt(iv,file_receiver_rsa_public_name)
    file_iv_encrypted=open('file_iv_encrypted','wb')
    file_iv_encrypted.write(iv_encrypted)
    file_iv_encrypted.close()
    printCN("对iv的RSA加密完成!")
    file_aes_key.close()

    printCN("加密过程结束!")
    printCN("你需要发送给接收者的文件有:")
    printCN("1.已加密文件:file_encrypted")
    printCN("2.加密后的AES秘钥文件:AES_key_encrypted")
    printCN("3.AES加密后的初始化向量文件:file_iv_encrypted")
    printCN("4.加密后的签名文件:file_signature_encrypted")
    printCN("5.填充位数文件:fill_number")
    printCN("\n最后请删除程序所在路径下加入和生成的文件,谢谢!")
    raw_inputCN("回车结束程序\n")
    return

def file_decrypt():
    printCN("请把以下文件放在与此程序同一路径下:")
    printCN("1.加密的文件")
    printCN("2.加密的AES秘钥文件")
    printCN("3.加密的签名文件")
    printCN("4.加密的iv文件")
    printCN("5.你的RSA私钥文件")
    printCN("6.发送者的RSA公钥文件")
    printCN("7.填充位数文件")
    raw_inputCN("放好之后,回车继续\n")

    file_aes_key_encrypted_name=raw_inputCN("请输入加密的AES秘钥文件名:\n")
    iv_encrypted_name=raw_inputCN("请输入加密的AES初始化向量文件名:\n")
    file_rsa_private_key_name=raw_inputCN("请输入你的RSA私钥文件名:\n")
    file_aes_key_encrypted=open(file_aes_key_encrypted_name,'rb')
    aes_key_encrypted=file_aes_key_encrypted.read()
    file_iv_encrypted=open(iv_encrypted_name,'rb')
    iv_encrypted=file_iv_encrypted.read()

    printCN("开始解密AES秘钥")
    aes_key=rsa_private_decrypt(aes_key_encrypted, file_rsa_private_key_name)
    printCN("AES秘钥解密完成!")
    printCN("开始解密AES初始化向量")
    iv=rsa_private_decrypt(iv_encrypted,file_rsa_private_key_name)
    printCN("AES初始化向量解密完成!")
    file_encrypted_name=raw_inputCN("请输入加密的文件名:\n")
    file_encrypted=open(file_encrypted_name,'rb')
    file_encrypted_msg=file_encrypted.read()

    file_fill_number_name=raw_inputCN("请输入填充位数文件名:\n")
    file_fill_number=open(file_fill_number_name,'rb')
    fill_number=file_fill_number.read()
    printCN("开始对加密文件进行AES解密")
    file_msg=aes_decrypt(file_encrypted_msg,aes_key,iv)
    file_msg=file_msg[0:len(file_msg)-int(fill_number)]     # 去掉AES加密时填充的位
    printCN("加密文件AES解密完成!")
    file_fill_number.close()
    file_decrypted=open('file_decrypted','wb')   # 解密内容输出到文件
    file_decrypted.write(file_msg)
    md5_file_msg=md5_encrypt(file_msg)        # 计算解密出来的文件的MD5值
    file_decrypted.close()
    file_encrypted.close()                         # 加密文件解密完成,关闭

    file_signature_encrypted_name=raw_inputCN("请输入加密的签名文件名:\n")
    file_signature_encrypted=open(file_signature_encrypted_name,'rb')
    signature_encrypted=file_signature_encrypted.read()
    printCN("加密签名文件AES解密")
    file_signature=aes_decrypt(signature_encrypted,aes_key,iv)
    printCN("加密签名文件AES解密完成!")
    file_signature_encrypted.close()
    file_aes_key_encrypted.close()         # AES解密完成,关闭相关文件
    file_iv_encrypted.close()

    sender_public_key_name=raw_inputCN("请输入发送者的公钥文件名:\n")
    printCN("开始签名文件RSA解密")
    md5_decrypted=rsa_public_decrypt(file_signature,sender_public_key_name)
    printCN("签名文件RSA解密完成,得到原文件MD5值!")

    if md5_file_msg==md5_decrypted:   # MD5值校验
        printCN("MD5值校验成功!")
    else:
        printCN("MD5值校验失败,请重新传输或检查错误原因")

    printCN("解密程序运行完毕,请提取解密文件,并删除此程序所在路径下导入及生成的文件,谢谢!")
    raw_inputCN("回车结束程序\n")

    return

# AES加密
def aes_encrypt(aes_file, key,iv):  # aes_file 文件,key 16-bytes 对称秘钥
    from Crypto.Cipher import AES
    from Crypto import Random
    cipher = AES.new(key, AES.MODE_OFB,iv)   # 生成了加密时需要的实际密码,这里采用OFB模式
    # if fs is a multiple of 16
    x = len(aes_file) % 16
    printCN("要加密文件的长度是: %d"%len(aes_file))
    printCN("需要填充的数据长度 : %d"%((16- x)%16))
    if x != 0:
        aes_file_pad = aes_file + '0'*(16 - x) # It should be 16-x
    else:
        aes_file_pad=aes_file
    msg = cipher.encrypt(aes_file_pad)
    return msg,(16- x)%16

# AES解密
def aes_decrypt(aes_file, key,iv):
    from Crypto.Cipher import AES
    cipher = AES.new(key, AES.MODE_OFB,iv)   # 生成了解密时需要的实际密码,这里采用OFB模式
    msg=cipher.decrypt(aes_file)
    return msg

# 计算MD5值
def md5_encrypt(md5_file):
    from Crypto.Hash import MD5
    msg = MD5.new()
    msg.update(md5_file)
    return msg.hexdigest()

# RSA私钥加密
def rsa_private_encrypt(msg,file_rsa_private_key_name):
    from M2Crypto import RSA    # 用M2Crypto下的RSA模块
    rsa_private_key=RSA.load_key(file_rsa_private_key_name)
    msg_encrypted=rsa_private_key.private_encrypt(msg,RSA.pkcs1_padding)
    return msg_encrypted

# RSA公钥加密
def rsa_public_encrypt(msg,file_rsa_public_name):
    from M2Crypto import RSA    # 用M2Crypto下的RSA模块
    rsa_public_key=RSA.load_pub_key(file_rsa_public_name)
    msg_encrypted=rsa_public_key.public_encrypt(msg,RSA.pkcs1_padding)
    return msg_encrypted

#  RSA私钥解密
def rsa_private_decrypt(msg,file_rsa_private_key_name):
    from M2Crypto import RSA    # 用M2Crypto下的RSA模块
    rsa_private_key=RSA.load_key(file_rsa_private_key_name)
    msg_decrypted=rsa_private_key.private_decrypt(msg,RSA.pkcs1_padding)
    return msg_decrypted

#  RSA公钥解密
def rsa_public_decrypt(msg,file_rsa_public_name):
    from M2Crypto import RSA    # 用M2Crypto下的RSA模块
    rsa_public_key=RSA.load_pub_key(file_rsa_public_name)
    msg_decrypted=rsa_public_key.public_decrypt(msg,RSA.pkcs1_padding)
    return msg_decrypted

变量命名过长(没什么办法啊,组织能力不够)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 密码学