前言:最近在想用spring-boot写个前后端登录加密的框架,供自己学习使用,随研究了下加密算法的实现,当然大学时自学过加密等安全类的东西(仅限理论),服务端从入门到现在学习了一年多,第一次点东西以加密算法源码查看为切入点
开篇:使用工具为intellij idea,查阅到java知道加密Messagedigest,遂研究使用下。当写道第一行时突然想看看实现的原理是什么
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
追溯下他的源码,于是按住ctr点击MessageDigest类,进入源码页面此时进入一个误区,在项目下的库里找了半天没找到包。
该文件为zip文件,为非jar包没有在该目录下列出。还纠结了好一会以为在哪个隐藏的路径里呢,其实在项目里查看路劲即可,点击该类单击右键即可复制全路径,so easy!
接着看源码,我们调用的是getInstance方法,同样的对着方法名按ctrl点击跳转,可查看该方法说明。
标注1是方法说明,该方法返回一个指定的加密算法的摘要对象。通过标注2可查看加密算法的加密原理,因为注释文档写的是相对路径,可以直接复制地址在百度搜索全路径,这里我给出算法地址,感兴趣的可自行研究-加密算法文档。具体内容点击行尾链接即可查看。
标注3说明生产者列表可以通过那个方法查看
接着查看,getInstance方法中调用了
Object[] objs = Security.getImpl(algorithm, "MessageDigest",(String)null);
同样的,点击getImpl查看源码。该方法的第一个参数就是我们使用的加密算法,然后传递给GetInstance里的getInstance方法,不过传递后参数位置变成了第三个参数。通过GetInstance.getInstance才算进入了核心,附上源码:
public static GetInstance.Instance getInstance(String var0, Class<?> var1, String var2) throws NoSuchAlgorithmException {
ProviderList var3 = Providers.getProviderList();
Service var4 = var3.getService(var0, var2);
if (var4 == null) {
throw new NoSuchAlgorithmException(var2 + " " + var0 + " not available");
} else {
try {
return getInstance(var4, var1);
} catch (NoSuchAlgorithmException var10) {
NoSuchAlgorithmException var5 = var10;
Iterator var6 = var3.getServices(var0, var2).iterator();
while(true) {
Service var7;
do {
if (!var6.hasNext()) {
throw var5;
}
var7 = (Service)var6.next();
} while(var7 == var4);
try {
return getInstance(var7, var1);
} catch (NoSuchAlgorithmException var9) {
var5 = var9;
}
}
}
}
}
核心为方法中的第一行和第二行:
ProviderList var3 = Providers.getProviderList();
Service var4 = var3.getService(var0, var2);
通过getService来判断调用的加密算法是否合理。点击进入查看getService方法:
public Service getService(String var1, String var2) {
for(int var3 = 0; var3 < this.configs.length; ++var3) {
Provider var4 = this.getProvider(var3);
Service var5 = var4.getService(var1, var2);
if (var5 != null) {
return var5;
}
}
return null;
}
可以看出这是需要从congfig里读取信息了。再接着查看config发现该变量在ProderList类中定义,其类型为ProverderConfig,见下面代码:
public final class ProviderList {
static final Debug debug = Debug.getInstance("jca", "ProviderList");
private static final ProviderConfig[] PC0 = new ProviderConfig[0];
private static final Provider[] P0 = new Provider[0];
static final ProviderList EMPTY;
private static final Provider EMPTY_PROVIDER;
private final ProviderConfig[] configs;
private volatile boolean allLoaded;
private final List<Provider> userList;
...//以下略
}
接着查看ProviderConfig即可发现重要信息:
final class ProviderConfig {
private static final Debug debug = Debug.getInstance("jca", "ProviderConfig");
private static final String P11_SOL_NAME = "sun.security.pkcs11.SunPKCS11";
private static final String P11_SOL_ARG = "${java.home}/lib/security/sunpkcs11-solaris.cfg";
private static final int MAX_LOAD_TRIES = 30;
private static final Class[] CL_STRING = new Class[]{String.class};
private final String className;
... //以下略
}
找到sun.security.pkcs11包下的SunPKCS11类,搜索MD5
至此验证加密算法是否合法的步骤已经完成!