「javajce源码」java的源码
本篇文章给大家谈谈javajce源码,以及java的源码对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、如何有效防止Java程序源码被人偷窥?
- 2、JAVA对DES加密解密的实现
- 3、JAVA中Given final block not properly padded怎么办
- 4、求RSA算法JAVA实现源代码(带界面的)
如何有效防止Java程序源码被人偷窥?
; Java程序的源代码很容易被别人偷看 只要有一个反编译器 任何人都可以分析别人的代码 本文讨论如何在不修改原有程序的情况下 通过加密技术保护源代码
一 为什么要加密?
对于传统的C或C++之类的语言来说 要在Web上保护源代码是很容易的 只要不发布它就可以 遗憾的是 Java程序的源代码很容易被别人偷看 只要有一个反编译器 任何人都可以分析别人的代码 Java的灵活性使得源代码很容易被窃取 但与此同时 它也使通过加密保护代码变得相对容易 我们唯一需要了解的就是Java的ClassLoader对象 当然 在加密过程中 有关Java Cryptography Extension(JCE)的知识也是必不可少的
有几种技术可以 模糊 Java类文件 使得反编译器处理类文件的效果大打折扣 然而 修改反编译器使之能够处理这些经过模糊处理的类文件并不是什么难事 所以不能简单地依赖模糊技术来保证源代码的安全
我们可以用流行的加密工具加密应用 比如PGP(Pretty Good Privacy)或GPG(GNU Privacy Guard) 这时 最终用户在运行应用之前必须先进行解密 但解密之后 最终用户就有了一份不加密的类文件 这和事先不进行加密没有什么差别
Java运行时装入字节码的机制隐含地意味着可以对字节码进行修改 JVM每次装入类文件时都需要一个称为ClassLoader的对象 这个对象负责把新的类装入正在运行的JVM JVM给ClassLoader一个包含了待装入类(比如java lang Object)名字的字符串 然后由ClassLoader负责找到类文件 装入原始数据 并把它转换成一个Class对象
我们可以通过定制ClassLoader 在类文件执行之前修改它 这种技术的应用非常广泛??在这里 它的用途是在类文件装入之时进行解密 因此可以看成是一种即时解密器 由于解密后的字节码文件永远不会保存到文件系统 所以窃密者很难得到解密后的代码
由于把原始字节码转换成Class对象的过程完全由系统负责 所以创建定制ClassLoader对象其实并不困难 只需先获得原始数据 接着就可以进行包含解密在内的任何转换
Java 在一定程度上简化了定制ClassLoader的构建 在Java 中 loadClass的缺省实现仍旧负责处理所有必需的步骤 但为了顾及各种定制的类装入过程 它还调用一个新的findClass方法
这为我们编写定制的ClassLoader提供了一条捷径 减少了麻烦 只需覆盖findClass 而不是覆盖loadClass 这种方法避免了重复所有装入器必需执行的公共步骤 因为这一切由loadClass负责
不过 本文的定制ClassLoader并不使用这种方法 原因很简单 如果由默认的ClassLoader先寻找经过加密的类文件 它可以找到;但由于类文件已经加密 所以它不会认可这个类文件 装入过程将失败 因此 我们必须自己实现loadClass 稍微增加了一些工作量
二 定制类装入器
每一个运行着的JVM已经拥有一个ClassLoader 这个默认的ClassLoader根据CLASSPATH环境变量的值 在本地文件系统中寻找合适的字节码文件
应用定制ClassLoader要求对这个过程有较为深入的认识 我们首先必须创建一个定制ClassLoader类的实例 然后显式地要求它装入另外一个类 这就强制JVM把该类以及所有它所需要的类关联到定制的ClassLoader Listing 显示了如何用定制ClassLoader装入类文件
【Listing 利用定制的ClassLoader装入类文件】
以下是引用片段
// 首先创建一个ClassLoader对象 ClassLoader myClassLoader = new myClassLoader(); // 利用定制ClassLoader对象装入类文件 // 并把它转换成Class对象 Class myClass = myClassLoader loadClass( mypackage MyClass ); // 最后 创建该类的一个实例 Object newInstance = myClass newInstance(); // 注意 MyClass所需要的所有其他类 都将通过 // 定制的ClassLoader自动装入
如前所述 定制ClassLoader只需先获取类文件的数据 然后把字节码传递给运行时系统 由后者完成余下的任务
ClassLoader有几个重要的方法 创建定制的ClassLoader时 我们只需覆盖其中的一个 即loadClass 提供获取原始类文件数据的代码 这个方法有两个参数 类的名字 以及一个表示JVM是否要求解析类名字的标记(即是否同时装入有依赖关系的类) 如果这个标记是true 我们只需在返回JVM之前调用resolveClass
【Listing ClassLoader loadClass()的一个简单实现】
以下是引用片段
public Class loadClass( String name boolean resolve ) throws ClassNotFoundException { try { // 我们要创建的Class对象 Class clasz = null; // 必需的步骤 如果类已经在系统缓冲之中 // 我们不必再次装入它 clasz = findLoadedClass( name ); if (clasz != null) return clasz; // 下面是定制部分 byte classData[] = /* 通过某种方法获取字节码数据 */; if (classData != null) { // 成功读取字节码数据 现在把它转换成一个Class对象 clasz = defineClass( name classData classData length ); } // 必需的步骤 如果上面没有成功 // 我们尝试用默认的ClassLoader装入它 if (clasz == null) clasz = findSystemClass( name ); // 必需的步骤 如有必要 则装入相关的类 if (resolve clasz != null) resolveClass( clasz ); // 把类返回给调用者 return clasz; } catch( IOException ie ) { throw new ClassNotFoundException( ie toString() ); } catch( GeneralSecurityException gse ) { throw new ClassNotFoundException( gse toString() ); } }
Listing 显示了一个简单的loadClass实现 代码中的大部分对所有ClassLoader对象来说都一样 但有一小部分(已通过注释标记)是特有的 在处理过程中 ClassLoader对象要用到其他几个辅助方法
findLoadedClass 用来进行检查 以便确认被请求的类当前还不存在 loadClass方法应该首先调用它
defineClass 获得原始类文件字节码数据之后 调用defineClass把它转换成一个Class对象 任何loadClass实现都必须调用这个方法
findSystemClass 提供默认ClassLoader的支持 如果用来寻找类的定制方法不能找到指定的类(或者有意地不用定制方法) 则可以调用该方法尝试默认的装入方式 这是很有用的 特别是从普通的JAR文件装入标准Java类时
resolveClass 当JVM想要装入的不仅包括指定的类 而且还包括该类引用的所有其他类时 它会把loadClass的resolve参数设置成true 这时 我们必须在返回刚刚装入的Class对象给调用者之前调用resolveClass
三 加密 解密
Java加密扩展即Java Cryptography Extension 简称JCE 它是Sun的加密服务软件 包含了加密和密匙生成功能 JCE是JCA(Java Cryptography Architecture)的一种扩展
JCE没有规定具体的加密算法 但提供了一个框架 加密算法的具体实现可以作为服务提供者加入 除了JCE框架之外 JCE软件包还包含了SunJCE服务提供者 其中包括许多有用的加密算法 比如DES(Data Encryption Standard)和Blowfish
为简单计 在本文中我们将用DES算法加密和解密字节码 下面是用JCE加密和解密数据必须遵循的基本步骤
步骤 生成一个安全密匙 在加密或解密任何数据之前需要有一个密匙 密匙是随同被加密的应用一起发布的一小段数据 Listing 显示了如何生成一个密匙 【Listing 生成一个密匙】
以下是引用片段
// DES算法要求有一个可信任的随机数源 SecureRandom sr = new SecureRandom(); // 为我们选择的DES算法生成一个KeyGenerator对象 KeyGenerator kg = KeyGenerator getInstance( DES ); kg init( sr ); // 生成密匙 SecretKey key = kg generateKey(); // 获取密匙数据 byte rawKeyData[] = key getEncoded(); /* 接下来就可以用密匙进行加密或解密 或者把它保存 为文件供以后使用 */ doSomething( rawKeyData ); 步骤 加密数据 得到密匙之后 接下来就可以用它加密数据 除了解密的ClassLoader之外 一般还要有一个加密待发布应用的独立程序(见Listing ) 【Listing 用密匙加密原始数据】
以下是引用片段
// DES算法要求有一个可信任的随机数源 SecureRandom sr = new SecureRandom(); byte rawKeyData[] = /* 用某种方法获得密匙数据 */; // 从原始密匙数据创建DESKeySpec对象 DESKeySpec dks = new DESKeySpec( rawKeyData ); // 创建一个密匙工厂 然后用它把DESKeySpec转换成 // 一个SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory getInstance( DES ); SecretKey key = keyFactory generateSecret( dks ); // Cipher对象实际完成加密操作 Cipher cipher = Cipher getInstance( DES ); // 用密匙初始化Cipher对象 cipher init( Cipher ENCRYPT_MODE key sr ); // 现在 获取数据并加密 byte data[] = /* 用某种方法获取数据 */ // 正式执行加密操作 byte encryptedData[] = cipher doFinal( data ); // 进一步处理加密后的数据 doSomething( encryptedData ); 步骤 解密数据 运行经过加密的应用时 ClassLoader分析并解密类文件 操作步骤如Listing 所示 【Listing 用密匙解密数据】
// DES算法要求有一个可信任的随机数源 SecureRandom sr = new SecureRandom(); byte rawKeyData[] = /* 用某种方法获取原始密匙数据 */; // 从原始密匙数据创建一个DESKeySpec对象 DESKeySpec dks = new DESKeySpec( rawKeyData ); // 创建一个密匙工厂 然后用它把DESKeySpec对象转换成 // 一个SecretKey对象 SecretKeyFactory keyFactory = SecretKeyFactory getInstance( DES ); SecretKey key = keyFactory generateSecret( dks ); // Cipher对象实际完成解密操作 Cipher cipher = Cipher getInstance( DES ); // 用密匙初始化Cipher对象 cipher init( Cipher DECRYPT_MODE key sr ); // 现在 获取数据并解密 byte encryptedData[] = /* 获得经过加密的数据 */ // 正式执行解密操作 byte decryptedData[] = cipher doFinal( encryptedData ); // 进一步处理解密后的数据 doSomething( decryptedData );
四 应用实例
前面介绍了如何加密和解密数据 要部署一个经过加密的应用 步骤如下
步骤 创建应用 我们的例子包含一个App主类 两个辅助类(分别称为Foo和Bar) 这个应用没有什么实际功用 但只要我们能够加密这个应用 加密其他应用也就不在话下
步骤 生成一个安全密匙 在命令行 利用GenerateKey工具(参见GenerateKey java)把密匙写入一个文件 % java GenerateKey key data
步骤 加密应用 在命令行 利用EncryptClasses工具(参见EncryptClasses java)加密应用的类 % java EncryptClasses key data App class Foo class Bar class
该命令把每一个 class文件替换成它们各自的加密版本
步骤 运行经过加密的应用 用户通过一个DecryptStart程序运行经过加密的应用 DecryptStart程序如Listing 所示 【Listing DecryptStart java 启动被加密应用的程序】
以下是引用片段
import java io *; import java security *; import java lang reflect *; import javax crypto *; import javax crypto spec *; public class DecryptStart extends ClassLoader { // 这些对象在构造函数中设置 // 以后loadClass()方法将利用它们解密类 private SecretKey key; private Cipher cipher; // 构造函数 设置解密所需要的对象 public DecryptStart( SecretKey key ) throws GeneralSecurityException IOException { this key = key; String algorithm = DES ; SecureRandom sr = new SecureRandom(); System err println( [DecryptStart: creating cipher] ); cipher = Cipher getInstance( algorithm ); cipher init( Cipher DECRYPT_MODE key sr ); } // main过程 我们要在这里读入密匙 创建DecryptStart的 // 实例 它就是我们的定制ClassLoader // 设置好ClassLoader以后 我们用它装入应用实例 // 最后 我们通过Java Reflection API调用应用实例的main方法 static public void main( String args[] ) throws Exception { String keyFilename = args[ ]; String appName = args[ ]; // 这些是传递给应用本身的参数 String realArgs[] = new String[args length ]; System arraycopy( args realArgs args length ); // 读取密匙 System err println( [DecryptStart: reading key] ); byte rawKey[] = Util readFile( keyFilename ); DESKeySpec dks = new DESKeySpec( rawKey ); SecretKeyFactory keyFactory = SecretKeyFactory getInstance( DES ); SecretKey key = keyFactory generateSecret( dks ); // 创建解密的ClassLoader DecryptStart dr = new DecryptStart( key ); // 创建应用主类的一个实例 // 通过ClassLoader装入它 System err println( [DecryptStart: loading +appName+ ] ); Class clasz = dr loadClass( appName ); // 最后 通过Reflection API调用应用实例 // 的main()方法 // 获取一个对main()的引用 String proto[] = new String[ ]; Class mainArgs[] = { (new String[ ]) getClass() }; Method main = clasz getMethod( main mainArgs ); // 创建一个包含main()方法参数的数组 Object argsArray[] = { realArgs }; System err println( [DecryptStart: running +appName+ main()] ); // 调用main() main invoke( null argsArray ); } public Class loadClass( String name boolean resolve ) throws ClassNotFoundException { try { // 我们要创建的Class对象 Class clasz = null; // 必需的步骤 如果类已经在系统缓冲之中 // 我们不必再次装入它 clasz = findLoadedClass( name ); if (clasz != null) return clasz; // 下面是定制部分 try { // 读取经过加密的类文件 byte classData[] = Util readFile( name+ class ); if (classData != null) { // 解密 byte decryptedClassData[] = cipher doFinal( classData ); // 再把它转换成一个类 clasz = defineClass( name decryptedClassData decryptedClassData length ); System err println( [DecryptStart: decrypting class +name+ ] ); } } catch( FileNotFoundException fnfe ) // 必需的步骤 如果上面没有成功 // 我们尝试用默认的ClassLoader装入它 if (clasz == null) clasz = findSystemClass( name ); // 必需的步骤 如有必要 则装入相关的类 if (resolve clasz != null) resolveClass( clasz ); // 把类返回给调用者 return clasz; } catch( IOException ie ) { throw new ClassNotFoundException( ie toString() ); } catch( GeneralSecurityException gse ) { throw new ClassNotFoundException( gse toString() ); } } } 对于未经加密的应用 正常执行方式如下 % java App arg arg arg
对于经过加密的应用 则相应的运行方式为 % java DecryptStart key data App arg arg arg
DecryptStart有两个目的 一个DecryptStart的实例就是一个实施即时解密操作的定制ClassLoader;同时 DecryptStart还包含一个main过程 它创建解密器实例并用它装入和运行应用 示例应用App的代码包含在App java Foo java和Bar java内 Util java是一个文件I/O工具 本文示例多处用到了它 完整的代码请从本文最后下载
五 注意事项
我们看到 要在不修改源代码的情况下加密一个Java应用是很容易的 不过 世上没有完全安全的系统 本文的加密方式提供了一定程度的源代码保护 但对某些攻击来说它是脆弱的
虽然应用本身经过了加密 但启动程序DecryptStart没有加密 攻击者可以反编译启动程序并修改它 把解密后的类文件保存到磁盘 降低这种风险的办法之一是对启动程序进行高质量的模糊处理 或者 启动程序也可以采用直接编译成机器语言的代码 使得启动程序具有传统执行文件格式的安全性
另外还要记住的是 大多数JVM本身并不安全 狡猾的黑客可能会修改JVM 从ClassLoader之外获取解密后的代码并保存到磁盘 从而绕过本文的加密技术 Java没有为此提供真正有效的补救措施
lishixinzhi/Article/program/Java/hx/201311/25751
JAVA对DES加密解密的实现
呃,貌似DES加密解密的时候可以不用尼个generatekey()方法的,比如说下面的代码
Cipher c = Cipher.getInstance("DES");
SecretKeySpec sk=new SecretKeySpec("00000000".getBytes(),"DES");
c.init(Cipher.ENCRYPT_MODE,sk);
byte encode[]=c.doFinal("0123456789".getBytes());
for(byte b:encode)System.out.print(b+",");
c.init(Cipher.DECRYPT_MODE,sk);
byte bb[]={76,114,-8,-106,-48,-75,-64,16,80,-106,106,-96,-25,61,124,-61};//0123456789的DES加密数组
byte decode[]=c.doFinal(bb);
System.out.println("\n"+new String(decode));
在这里可以看到有关JCA的说明:
JAVA中Given final block not properly padded怎么办
获取Cipher对象时必须要写成:Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
不能写成:Cipher cipher = Cipher.getInstance("DES");
否则解密时候报错:Given final block not properly padded
原因:Cipher cipher = Cipher.getInstance("DES");与Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
等同,填充方式错误,加密的时候会得到16长度的字节数组。
解密时报错: javax.crypto.BadPaddingException: Given final block not properly padded
仔细分析一下,不难发现,该异常是在解密的时候抛出的,加密的方法没有问题。
但是两个方法的唯一差别是Cipher对象的模式不一样,这就排除了程序写错的可能性。再看一下异常的揭示信息,大概的意思是:提供的字块不符合填补的。
原来在用DES加密的时候,最后一位长度不足64的,它会自动填补到64,那么在我们进行字节数组到字串的转化过程中,可以把它填补的不可见字符改变了,所以引发系统抛出异常。
为了方便使用,我们再写一个新的方法封装一下原来的方法:
public static String DataEncrypt(String str, byte[] key) {
String encrypt = null;
try {
byte[] ret = encode(str.getBytes("UTF-8"),key);
encrypt = new String(Base64.encode(ret));
}
catch(Exception e){
System.out.print(e); encrypt = str;
}
return encrypt;
}
public static String DataDecrypt(String str, byte[] key) {
String decrypt = null;
try {
byte[] ret = decode(Base64.decode(str),key);
decrypt = new String(ret,"UTF-8");
}
catch(Exception e) {
System.out.print(e);
decrypt = str;
}
return decrypt;
}
扩展资料:
java中的Cipher类
位于javax.crypto包下,声明为 public class Cipher extends Object
此类为加密和解密提供密码功能。它构成了 Java Cryptographic Extension (JCE) 框架的核心。
为创建 Cipher 对象,应用程序调用 Cipher 的 getInstance 方法并将所请求转换 的名称传递给它。还可以指定提供者的名称(可选)。
转换 是一个字符串,它描述为产生某种输出而在给定的输入上执行的操作(或一组操作)。转换始终包括加密算法的名称(例如,DES),后面可能跟有一个反馈模式和填充方案。
转换具有以下形式:
“算法/模式/填充”或“算法”
(后一种情况下,使用模式和填充方案特定于提供者的默认值)。例如,以下是有效的转换:
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
使用 CFB 和 OFB 之类的模式,Cipher 块可以加密单元中小于该 Cipher 的实际块大小的数据。请求这样一个模式时,可以指定一次处理的位数(可选):将此数添加到模式名称中,正如 "DES/CFB8/NoPadding" 和 "DES/OFB32/PKCS5Padding" 转换所示。
如果未指定该数,则将使用特定于提供者的默认值。(例如,SunJCE 提供者对 DES 使用默认的 64 位)。因此,通过使用如 CFB8 或 OFB8 的 8 位模式,Cipher 块可以被转换为面向字节的 Cipher 流。
1、字段
public static final int ENCRYPT_MODE 用于将 Cipher 初始化为加密模式的常量。
public static final int DECRYPT_MODE 用于将 Cipher 初始化为解密模式的常量。
public static final int WRAP_MODE 用于将 Cipher 初始化为密钥包装模式的常量。
public static final int UNWRAP_MODE 用于将 Cipher 初始化为密钥解包模式的常量。
public static final int PUBLIC_KEY 用于表示要解包的密钥为“公钥”的常量。
public static final int PRIVATE_KEY 用于表示要解包的密钥为“私钥”的常量。
public static final int SECRET_KEY 用于表示要解包的密钥为“秘密密钥”的常量。
求RSA算法JAVA实现源代码(带界面的)
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.io.*;
import java.math.BigInteger;
/**
* RSA 工具类。提供加密,解密,生成密钥对等方法。
* 需要到下载bcprov-jdk14-123.jar。
* @author xiaoyusong
* mail: xiaoyusong@etang.com
* msn:xiao_yu_song@hotmail.com
* @since 2004-5-20
*
*/
public class RSAUtil {
/**
* 生成密钥对
* @return KeyPair
* @throws EncryptException
*/
public static KeyPair generateKeyPair() throws EncryptException {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
new org.bouncycastle.jce.provider.BouncyCastleProvider());
final int KEY_SIZE = 1024;//没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGen.genKeyPair();
return keyPair;
} catch (Exception e) {
throw new EncryptException(e.getMessage());
}
}
/**
* 生成公钥
* @param modulus
* @param publicExponent
* @return RSAPublicKey
* @throws EncryptException
*/
public static RSAPublicKey generateRSAPublicKey(byte[] modulus, byte[] publicExponent) throws EncryptException {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new EncryptException(ex.getMessage());
}
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));
try {
return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
throw new EncryptException(ex.getMessage());
}
}
/**
* 生成私钥
* @param modulus
* @param privateExponent
* @return RSAPrivateKey
* @throws EncryptException
*/
public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus, byte[] privateExponent) throws EncryptException {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new EncryptException(ex.getMessage());
}
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));
try {
return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
} catch (InvalidKeySpecException ex) {
throw new EncryptException(ex.getMessage());
}
}
/**
* 加密
* @param key 加密的密钥
* @param data 待加密的明文数据
* @return 加密后的数据
* @throws EncryptException
*/
public static byte[] encrypt(Key key, byte[] data) throws EncryptException {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, key);
int blockSize = cipher.getBlockSize();//获得加密块大小,如:加密前数据为128个byte,而key_size=1024 加密块大小为127 byte,加密后为128个byte;因此共有2个加密块,第一个127 byte第二个为1个byte
int outputSize = cipher.getOutputSize(data.length);//获得加密块加密后块大小
int leavedSize = data.length % blockSize;
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize 0) {
if (data.length - i * blockSize blockSize)
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
else
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
//这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了OutputSize所以只好用dofinal方法。
i++;
}
return raw;
} catch (Exception e) {
throw new EncryptException(e.getMessage());
}
}
/**
* 解密
* @param key 解密的密钥
* @param raw 已经加密的数据
* @return 解密后的明文
* @throws EncryptException
*/
public static byte[] decrypt(Key key, byte[] raw) throws EncryptException {
try {
Cipher cipher = Cipher.getInstance("RSA", new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, key);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
} catch (Exception e) {
throw new EncryptException(e.getMessage());
}
}
/**
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
File file = new File("test.html");
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] tmpbuf = new byte[1024];
int count = 0;
while ((count = in.read(tmpbuf)) != -1) {
bout.write(tmpbuf, 0, count);
tmpbuf = new byte[1024];
}
in.close();
byte[] orgData = bout.toByteArray();
KeyPair keyPair = RSAUtil.generateKeyPair();
RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey priKey = (RSAPrivateKey) keyPair.getPrivate();
byte[] pubModBytes = pubKey.getModulus().toByteArray();
byte[] pubPubExpBytes = pubKey.getPublicExponent().toByteArray();
byte[] priModBytes = priKey.getModulus().toByteArray();
byte[] priPriExpBytes = priKey.getPrivateExponent().toByteArray();
RSAPublicKey recoveryPubKey = RSAUtil.generateRSAPublicKey(pubModBytes,pubPubExpBytes);
RSAPrivateKey recoveryPriKey = RSAUtil.generateRSAPrivateKey(priModBytes,priPriExpBytes);
byte[] raw = RSAUtil.encrypt(priKey, orgData);
file = new File("encrypt_result.dat");
OutputStream out = new FileOutputStream(file);
out.write(raw);
out.close();
byte[] data = RSAUtil.decrypt(recoveryPubKey, raw);
file = new File("decrypt_result.html");
out = new FileOutputStream(file);
out.write(data);
out.flush();
out.close();
}
}
这个行吧
再参考这个吧
javajce源码的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java的源码、javajce源码的信息别忘了在本站进行查找喔。
发布于:2023-01-28,除非注明,否则均为
原创文章,转载请注明出处。