比特币私钥生成器(比特币私钥生成公钥使用哪个算法)

) as out_file: session_key = get_random_bytes(16) # 这里是将文件最终搞成AES加密 cipher_sess...

Bitget下载

注册下载Bitget下载,邀请好友,即有机会赢取 3,000 USDT

APP下载   官网注册

本文教你如何用Python与Java对文件进行不对称加密,并且Python与Java共用一套密钥,可以相互加解密对方的密文。本文仅作技术交流,请不要用于任何违法用途。

一、引言

最近有个项目需要做文件加密,并且要求python与java能够相互加解密。对于文件加密,我第一时间想到了比特币勒索病毒。于是收集了相关的信息,参考瑞星官网的《又一使用.net开发的勒索病毒出现——Prodecryptor勒索病毒》这篇文章,大致了解到程序先使用RSA对AES算法的密钥进行加密,然后使用AES算法对文件进行加密。

二、RSA与AES简介

RSA加密算法属于非对称加密算法,AES加密算法属于对称加密算法。这里我们不聊RSA与AES算法的具体实现,我们先聊下对称加密与非对称基本情况。

1、对称加密速度快,但是只有一个密钥进行加密和解密。当你的程序加密时,别人能反编译你的程序获取密钥,导致密钥泄露。

2、非对称加密速度慢,在加密中采用两个密钥,使用公钥进行加密,私钥进行解密。在程序中使用公钥进行加密,别人即使拿到了你的公钥也无法对文件进行解密。但是每次加密有长度限制,如果加密信息较多,需分段加解密(不建议对大量信息rsa加密,效率低效)。

因此在比特币勒索病毒程序中加密过程如下:1读取文件字节数组(加密算法都是对字节数组进行加密)2创建一个随机AES密钥,作为session密钥。3使用RSA算法对AES的session密钥加密覆盖写入文件。4然后使用AES的session密钥对文件内容进行加密写入文件。

解密过程:1读取加密后的文件字节数组,2使用私钥对AES的密钥进行解密,3使用AES对文件内容解密,4将解密后的文件内容覆盖写入文件中。

三、python与java交互遇到的一些问题

根据网上的例子,如果单独使用python或者java按上述方式进行文件加解密都很容易找到实现方案,但是如果python和java进行交互可能会出现一些问题。由于我学艺不精,采用了一些投机取巧的方法。

在java代码中我使用的是javax.crypto.Cipher模块。python中使用的是Crypto.Cipher的AES模块,以及RSA模块(也可以直接使用Crypto.Cipher的RSA模块)

问题1 Python与Java生成的RSA密钥无法相互导入

JAVA的RSAKeyPairGenerator并没有公开,因此我无法确定JAVA是如何导入相关的key。根据网上的一些方法,踩坑两小时依旧无果。最后解决方法:在对JAVA代码生成密钥debug过程中找到相应的n ,e ,d ,p ,q参数的值,也可以使用反射的方法找到这些值(私有属性,无法直接获取)。在python的rsa.newkeys函数源码中,发现可以通过 ( PublicKey(n, e), PrivateKey(n, e, d, p, q) )这种方式导入相应的key。在Crypto.PublicKey的RSA模块中可以根据RSA.generate函数的源码找到RsaKey(n=n, e=e, d=d, p=p, q=q, u=u)这段代码导入相应的key。通过这种方式就可以python与Java使用同一套密钥了。

问题2 Python使用AES加密后的内容,python可以解密但是Java无法解密。 后发现是数据进行padding时两边不一致导致的,后将函数改为以下得到解决

# 数据补空格padding = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16).encode()

四、python相关代码

以下为python加密模块内容,相应的密钥是通过【内容三】中的问题1获取得到。在实际项目中应该只保留公钥部分,私钥及解密部分应该剔除,下面java相关内容中也是如此。

"""信息加密模块"""import rsafrom rsa.key import PublicKey, PrivateKeyfrom Crypto.Random import get_random_bytesfrom Crypto.Cipher import AESn = 125720733811994291169610359480915027242498332835983573581162897380161904809997273335081454438575169422082365180940876618145332064877333466150617673634912674691272686174191003876154229771482350657467474462371208540453058063685991322556840489981457202800248228247442801463255542794487793252246277195836743728807e = 65537d = 19137129262988160103575582437121142435130740930646384943553733986366406188634401922437288699196269132775282283977999986917585984698968195955239969973936686417032907212206649527011774897714725474886031049229542718237754549863294574561095602754592205273482485305289414428603551207636838864047226576028764734081p = 12485487274433155882855920331622116862134407135211164113507239786605989655388750120598556263544308444761407796178741288699689788828502980217890667645001833q = 10069349401319384440381523925066814369492626716870156920501823163204449469801788824691171814613081997769220084438138226773387889070138894859614591998248079(pubkey, privkey) = (PublicKey(n, e), PrivateKey(n, e, d, p, q))def rsa_encrypt_file(file_path):    """公钥加密文件"""    with open(file_path, 'rb') as f:        data = f.read()    with open(file_path, 'wb') as out_file:        session_key = get_random_bytes(16)        # 这里是将文件最终搞成AES加密        cipher_session = rsa.encrypt(session_key, pubkey)        # aes的临时密钥        out_file.write(cipher_session)        # aes加密        mode = AES.MODE_ECB        cryptos = AES.new(session_key, mode)        # 数据补空格        padding = lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16).encode()        # AES加密后的密文字节数组        cipher_text = cryptos.encrypt(padding(data))        out_file.write(cipher_text)def rsa_decrypt_file(file_path):    """私钥解密文件"""    with open(file_path, 'rb') as f:        # 此处可以加passphrase, 类似盐值,但通过rsa模块生成的时候不支持此参数        # 因为rsa加密是128位,所以前128位为aes密钥        enc_session_key, cipher_text = [f.read(x) for x in (128, -1)]        # rsa解密aes密钥        session_key = rsa.decrypt(enc_session_key, privkey)        # aes对文件内容解密        cipher_aes = AES.new(session_key, AES.MODE_ECB)        data = cipher_aes.decrypt(cipher_text)        '''        去除内容末尾的相同的字符,因为加密过程中对未满16位的做了补充        具体可以参考lambda s: s + (16 - len(s) % 16) * chr(16 - len(s) % 16).encode()这段代码        下面代码应该还要校验c是否等于16 - len(s) % 16        '''        c = data[-1]        index = 0        if c < 16:            for i, d in enumerate(data[::-1]):                if d == c:                    index = i                else:                    break        data = data[:- 1 - index]    with open(file_path, 'wb') as f:        f.write(data)if __name__ == '__main__':    rsa_encrypt_file(r'd:\1.txt')    rsa_decrypt_file(r'd:\1.txt')

四、java相关代码

最近写python代码写得比较多,函数及属性的命名都没有按照Java的驼峰命名方式,大家随意看看哈。

main.java

import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;public class Main { public static void main(String[] args) throws Exception {  rsa_encrypt_file("d:\\1.txt");  rsa_decrypt_file("d:\\1.txt"); } /**  * 字节数组复制  * @param original 原始的字节数组  * @param start 要复制的开始位置下标  * @param end 要复制的结束位置下标  * @return  */ public static byte[] copy_array(byte[] original, int start, int end) {  int newLength = end - start;  byte[] copy = new byte[newLength];  System.arraycopy(original, start, copy, 0, Math.min(original.length, newLength));  return copy; } /**  * rsa对文件解密,先解密aes密钥,再解密文件  *   * @param file_path  * @throws Exception  */ public static void rsa_decrypt_file(String file_path) throws Exception {  // 读取数据  File f = new File(file_path);  int length = (int) f.length();  byte[] data = new byte[length];  FileInputStream fis = new FileInputStream(f);  fis.read(data);  fis.close();  // 解密  byte[] enc_session_key = copy_array(data, 0, 128);  byte[] session_key = RSAUtils.decrypt(enc_session_key, RSAUtils.privateKeyString);  byte[] cipher_text = copy_array(data, 128, data.length);  byte[] text = AESUtil.aes_decrypt(cipher_text, session_key);  // 写入文件  FileOutputStream fos = new FileOutputStream(f);  fos.write(text);  fos.flush();  fos.close(); } /**  * rsa对文件加密,先加密aes密钥,再加密文件  *   * @param file_path  * @throws Exception  */ public static void rsa_encrypt_file(String file_path) throws Exception {  // 读取数据  File f = new File(file_path);  int length = (int) f.length();  byte[] data = new byte[length];  FileInputStream fis = new FileInputStream(f);  fis.read(data);  fis.close();  // aes的随机密钥  byte[] session_key = AESUtil.create_aes_Key();  // 使用rsa对aes的密钥加密  byte[] cipher_session = RSAUtils.encrypt(session_key, RSAUtils.publicKeyString);  // 使用aes算法对文件内容加密  byte[] cipher_data = AESUtil.aes_encrypt(data, session_key);  // 将密钥写入文件  FileOutputStream fos = new FileOutputStream(f);  fos.write(cipher_session);  fos.write(cipher_data);  fos.flush();  fos.close(); }}

AESUtil.java

import java.security.Key;import java.security.NoSuchAlgorithmException;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;public class AESUtil { /**  * 创建128位的随机密钥  *   * @return  * @throws NoSuchAlgorithmException  */ public static byte[] create_aes_Key() throws NoSuchAlgorithmException {  // 生成key  KeyGenerator keyGenerator;  // 构造密钥生成器,指定为AES算法,不区分大小写  keyGenerator = KeyGenerator.getInstance("AES");  // 生成一个128位的随机源,根据传入的字节数组  keyGenerator.init(128);  // 产生原始对称密钥  SecretKey secretKey = keyGenerator.generateKey();  // 获得原始对称密钥的字节数组  byte[] keyBytes = secretKey.getEncoded();  // key转换,根据字节数组生成AES密钥  // Key key = new SecretKeySpec(keyBytes, "AES");  return keyBytes; } /**  * AES解密  *  * @param cipherText 加密后的密文byte数组  * @param key_byte   解密用密钥  */ public static byte[] aes_decrypt(byte[] cipherText, byte[] key_byte) {  Cipher cipher;  byte[] result = null;  try {   Key key = new SecretKeySpec(key_byte, "AES");   cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");   // 初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY   cipher.init(Cipher.DECRYPT_MODE, key);   result = cipher.doFinal(cipherText);  } catch (Exception e) {   e.printStackTrace();  }  return result; } /**  * AES加密  *   * @param context 需要加密的明文 KEYSTR 加密用密钥  * @return  */ public static byte[] aes_encrypt(byte[] context, byte[] key_byte) {  try {   Key key = new SecretKeySpec(key_byte, "AES");   Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");   cipher.init(Cipher.ENCRYPT_MODE, key);   // 将加密并编码后的内容解码成字节数组   return cipher.doFinal(context);  } catch (Exception e) {   e.printStackTrace();   return null;  } }}

RSAUtils.java

此处密钥是通过【内容三】中的问题1获取得到的。生成的密钥步骤可以参考genKeyPair函数

import javax.crypto.Cipher;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;import java.util.Base64;public class RSAUtils { private static Base64.Decoder decoder = Base64.getDecoder(); private static Base64.Encoder encoder = Base64.getEncoder(); // 预先得到的公钥和私钥 public static String publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzCEKyIaoSOCd+8XG/u6X9fGGlgmqygZPAWAYpSaPebX4kUm2yloxLdTAwYbCQmMhcgyOvxdo9H9Qjc/uw1SY43mvIAqXaRNQ9FYbzMCcV167ebjJF4xFjPICf5bQqBh4mt5vuf0CM1lpZazI7rsI2R5/pdVwmVXKFEVmqpuu+pwIDAQAB"; public static String privateKeyString = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALMIQrIhqhI4J37xcb+7pf18YaWCarKBk8BYBilJo95tfiRSbbKWjEt1MDBhsJCYyFyDI6/F2j0f1CNz+7DVJjjea8gCpdpE1D0VhvMwJxXXrt5uMkXjEWM8gJ/ltCoGHia3m+5/QIzWWllrMjuuwjZHn+l1XCZVcoURWaqm676nAgMBAAECgYAbQI6mfulcjJ+2expNjUrfIyfaAdgsA/1xsfR+JG+FVDV3YfTA0pnYgqYrNzOhTyBwtKWiBAQMeePY4bbWXBvNGsCSd7pwP4Io2B24fm4yKSIUbjJKx2jQMbLn+kvNu9Tw508ogmEfnHzUmVy0h2ePN+6hTUCZ7jjaNFlK2oACgQJBAO5jymEpoTdqFluIt2ETc6ElW9yPg1IrIJNT2QSPMS1i2xd/BmPP9PQMcV4hHv7knLFeLAjVaf0QFJ0SetlqYGkCQQDAQfRiii7xbt0sYMIrSWe4ygjSvxC9Job1dtgyI1Q2EjfO6wZzd+7Iu+pbC2sA2fCk40YMmxSmvCQoOuO/RESPAkEA1IjZfOi9mAcYKcFpJL5P38LL9IdqoA5dO5yMpjj3siwpgvg3/TMBg7e4NyC2Xq/5V1TLU5DZrsnwZt1782yYyQJBAL+4hcZGWm20yqZYjwivmNlzz7ypgD2/z9G0g//rryyEmlajlLlNHjfa/OdxyXD95LXpVo93ju5+q+faYgb4Qw0CQG6d0blzJS9qmnkP61Q49bBfiOPLF5MF9T+VyXe7zyjGKdrnT6WUucGTjjdVW1FX1mkMBtUdu9VPnbGiYzvoyuM="; public static void main(String[] args) throws Exception {  genKeyPair();  // 加密字符串//  String message = "df723820";//  String messageEn = encrypt(message, publicKeyString);//  System.out.println(message + "\t加密后的字符串为:" + messageEn);//  String messageDe = decrypt(messageEn, privateKeyString);//  System.out.println("还原后的字符串为:" + messageDe); } /**  * 随机生成密钥对  *  * @throws NoSuchAlgorithmException  */ public static void genKeyPair() throws NoSuchAlgorithmException {  // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象  KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  // 初始化密钥对生成器,密钥大小为96-1024位  keyPairGen.initialize(1024, new SecureRandom());  // 生成一个密钥对,保存在keyPair中  KeyPair keyPair = keyPairGen.generateKeyPair();  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥  System.out.println(publicKey.getModulus());  System.out.println(publicKey.getPublicExponent());  publicKeyString = new String(Base64.getEncoder().encodeToString(publicKey.getEncoded()));  // 得到私钥字符串  privateKeyString = new String(Base64.getEncoder().encodeToString(privateKey.getEncoded()));  System.out.println("生成的公钥:" + publicKeyString);  System.out.println("生成的私钥:" + privateKeyString); } /**  * RSA公钥加密  *  * @param str       加密字符串  * @param publicKey 公钥  * @return 密文  * @throws Exception 加密过程中的异常信息  */ public static String encrypt(String str, String publicKey) throws Exception {  // base64编码的公钥  byte[] decoded = decoder.decode(publicKey);  RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")    .generatePublic(new X509EncodedKeySpec(decoded));  // RSA加密  Cipher cipher = Cipher.getInstance("RSA");  cipher.init(Cipher.ENCRYPT_MODE, pubKey);  String outStr = encoder.encodeToString(cipher.doFinal(str.getBytes("UTF-8")));  return outStr; } /**  * RSA私钥解密  *  * @param str        加密字符串  * @param privateKey 私钥  * @return 铭文  * @throws Exception 解密过程中的异常信息  */ public static String decrypt(String str, String privateKey) throws Exception {  // 64位解码加密后的字符串  byte[] inputByte = decoder.decode(str.getBytes("UTF-8"));  // base64编码的私钥  byte[] decoded = decoder.decode(privateKey);  RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")    .generatePrivate(new PKCS8EncodedKeySpec(decoded));  // RSA解密  Cipher cipher = Cipher.getInstance("RSA");  cipher.init(Cipher.DECRYPT_MODE, priKey);  String outStr = new String(cipher.doFinal(inputByte));  return outStr; } public static byte[] decrypt(byte[] inputByte, String privateKey) throws Exception {  // base64编码的私钥  byte[] decoded = decoder.decode(privateKey);  // base64编码的私钥  RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")    .generatePrivate(new PKCS8EncodedKeySpec(decoded));  // RSA解密  Cipher cipher = Cipher.getInstance("RSA");  cipher.init(Cipher.DECRYPT_MODE, priKey);  return cipher.doFinal(inputByte); } public static byte[] encrypt(byte[] inputByte, String publicKey) throws Exception {  // base64编码的公钥  byte[] decoded = decoder.decode(publicKey);  RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")    .generatePublic(new X509EncodedKeySpec(decoded));  // RSA加密  Cipher cipher = Cipher.getInstance("RSA");  cipher.init(Cipher.ENCRYPT_MODE, pubKey);  return cipher.doFinal(inputByte); }}
上一篇: chia币今日价格行情(chia币价格今日期货行情)
下一篇: 比特大陆正式宣布停止蚂蚁矿机向中国发货(长期订单将执行替代方案)
《比特币私钥生成器(比特币私钥生成公钥使用哪个算法)》文档下载: PDF DOC TXT

猜你喜欢