记一次加解密问题导致的线上事故

记一次加解密问题导致的线上事故

题记

经过大家的艰苦奋战,完成了一次大版本上线,所涉及的产品、交易较多,测试方面也投入了较大精力,相关交易验证完毕后,大家高兴的散去。

果然,刚到家打开手机,还是出事了,存量未修改的部分产品风控拒绝率飙升,通过业务监控指标来看,这种拒绝率很有可能是代码导致的。

还是原来的套路,还是熟悉的配方,打开电脑连上VPN,经过交易数据分析,结合相关日志情况,清楚的发现部分数据源加密异常了。

相关报错信息

tried to access method org.bouncycastle.math.ec.ECPoint$Fp.(Lorg/bouncycastle/math/ec/ECCure;Lorg/bouncycastle/math/ec/ECFieldElement;)V from class com.zgcbank.rds.sm.SM2

‘Fp(org.bouncycastle.math.ec.ECCure, org.bouncycastle.math.ec.ECFoieldElement)’ is not public in ‘org.bouncycastle.math.ec.ECPoint.Fp’. Cannot be accessed from outside package

问题分析

第一步

根据报错信息,发现试图访问方法#Fp,发现非public类型方法,包外无法访问。

第二步

1.排查相关报错的数据接口依赖信息,发现代码中依赖了三个版本的jdk15on的包:

<dependency>
     <groupId>org.bouncycastlegroupId>
     <artifactId>bcprov-jdk15onartifactId>
     <version>1.65version>
 dependency>
<dependency>
     <groupId>org.bouncycastlegroupId>
     <artifactId>bcprov-jdk15onartifactId>
     <version>1.59vCureersion>
 dependency>
<dependency>
     <groupId>org.bouncycastlegroupId>
     <artifactId>bcprov-jdk15onartifactId>
     <version>1.52version>
 dependency>
第三步

排查相关依赖包:bcprov-jdk15on-1.52 ~ bcprov-jdk15on-1.65

  1. bcprov-jdk15on-1.52

public static class Fp extends ECCurve.AbstractFp {
        private static final int FP_DEFAULT_COORDS = 4;
        BigInteger q;
        BigInteger r;
        org.bouncycastle.math.ec.ECPoint.Fp infinity;

        public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
            this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
        }
        ......

public static class Fp extends ECPoint.AbstractFp {
		@Deprecated
        public Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
            this(var1, var2, var3, false);
        }

  1. bcprov-jdk15on-1.59
public static class Fp extends ECCurve.AbstractFp {
        private static final int FP_DEFAULT_COORDS = 4;
        BigInteger q;
        BigInteger r;
        org.bouncycastle.math.ec.ECPoint.Fp infinity;

public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
            this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
        }
	......
	
   public static class Fp extends ECPoint.AbstractFp {
        /** @deprecated */
        public Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
            this(var1, var2, var3, false);
        }

  1. bcprov-jdk15on-1.65
public static class Fp extends ECCurve.AbstractFp {
        private static final int FP_DEFAULT_COORDS = 4;
        BigInteger q;
        BigInteger r;
        org.bouncycastle.math.ec.ECPoint.Fp infinity;

        /** @deprecated */
        public Fp(BigInteger var1, BigInteger var2, BigInteger var3) {
            this(var1, var2, var3, (BigInteger)null, (BigInteger)null);
        }
		......
		
  public static class Fp extends ECPoint.AbstractFp {
        Fp(ECCurve var1, ECFieldElement var2, ECFieldElement var3) {
            super(var1, var2, var3);
        }
		
第四步

根据上述#Fp(ECCurve , ECFieldElement , ECFieldElement )相关信息,得出结论 bcprov-jdk15on-1.52 、 bcprov-jdk15on-1.59、 bcprov-jdk15on-1.65三个包中,前两个满足访问条件,继续分析。

第五步

分析相关依赖在项目中的影响,根据maven依赖调用链路分析,1.59该版本使用相对独立,鉴于目前BUG紧急修复的情况,确定可以先不动。

接下来就是1.521.65两个冲突版本的分析了,由第三步源码分析得出,两个版本Class使用方式不一致,检查代码发现各自版本皆有引用,且第三方数据加密格式不尽相同,短时间很难去完成版本统一改造升级。

解决方案

第一步

鉴于此,第一思路就是尝试重新写引用较少的1.65版本代码,重新写了10个类之后,发现引用的内容较多,重写的工作量较大,且影响代码整洁性。

有没有方式能兼容两套加解密的方式呢,从包构建的角度,我要改变其中一个版本(优先选择使用较少的1.65)的包路径,考虑采用 maven-shade-plugin实现。

上手开发

第一步

maven-shade-plugin相关依赖包导入私服,版本如下

<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-shade-pluginartifactId>
<version>3.2.4version>
第二步

建立空的maven工程在pom文件中完成maven-shade-plugin相关包构建plugin引入,并完成打包构建。

<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.pluginsgroupId>
        <artifactId>maven-shade-pluginartifactId>
        <version>3.2.4version>
        <executions>
          <execution>
            <phase>packagephase>
            <goals>
              <goal>shadegoal>
            goals>
            <configuration>
              <relocations>
                <relocation>
               	   
                   <pattern>org.bouncycastlepattern>
                   <shadedPattern>shaded.org.bouncycastleshadedPattern>
                   
                relocation>
              relocations>
            configuration>
          execution>
        executions>
      plugin>
    plugins>
  build>

功能验证

第一步
  1. 包构建信息如下,查看相关目录结构。
    记一次加解密问题导致的线上事故_第1张图片
    2.构建的maven包结构如下
    记一次加解密问题导致的线上事故_第2张图片
    3.jarClass文件包路径
    记一次加解密问题导致的线上事故_第3张图片
第二步

完成代码中1.65版本相关内容的替换,进行相关数据接口验证。
相关应用(引用了1.651.52版本jar)的应用节点启动报错:
java.lang.SecurityException:Invalid singnature file digest for Manifest main attributes
at sun security.util.SignatureFileVerfier.processImpl(SignatureFileVerfier.java:330)

方案一
  • 删除`第三步标题2中`红框中相关信息,重启应用,正常。
    
    • services
      versions
      BC1024KE.SF
      BC1024KE.DSA
      BC2048KE.SF
      BC2048KE.DSA
方案二
  •   在上述pom文件节点configuration中增加过滤器,重启应用,正常。
    
<filters>
  <filter>
      <artifact>*:*artifact>
      <excludes>
          <exclude>META-INF/*.SFexclude>
          <exclude>META-INF/*.DSAexclude>
          <exclude>META-INF/*.RSAexclude>
          <exclude>META-INF/services/*exclude>
          <exclude>META-INF/versions/*exclude>
      excludes>
  filter>
filters>

测试1.52版本相关数据接口正常,测试1.65接口报错:
Connect to xx.xxx.xx.xx:9009 [ /xx.xxx.xx.xx] failed Connection refused :connect

第三步
  1. 排查上述问题:Connect to xx.xxx.xx.xx:9009 [ /xx.xxx.xx.xx] failed Connection refused :connect

  2. 经检查,发现是使用了原来的httpclient导致的问题,每次创建新的链接即可,本文暂不扩展,待后续补充。

你可能感兴趣的:(maven-shade,bcprov-jdk15on,ECPoint,ECCure,Http,Connct)