From 5ff3e8867b460b5e676be166e7c6a5f2eaf4a41d Mon Sep 17 00:00:00 2001 From: RenFengJiang <1111> Date: Thu, 11 Jan 2024 17:42:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=87=86=E5=88=99=EF=BC=9A?= =?UTF-8?q?=E4=BD=BF=E7=94=A8RSA=E6=9C=80=E4=BC=98=E5=8A=A0=E5=AF=86?= =?UTF-8?q?=E5=A1=AB=E5=85=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rules/checkers/DynamicCodeChecker.java | 3 - .../checkers/DynamicLibraryLoadChecker.java | 6 ++ .../rules/checkers/RSAEncryptionChecker.java | 70 +++++++++++++++++++ .../java/rules/java/RSAEncryptionChecker.htm | 9 +++ .../java/rules/java/RSAEncryptionChecker.json | 13 ++++ .../src/test/files/RSAEncryptionRule.java | 30 ++++++++ .../DynamicLibraryLoadCheckerTest.java | 6 ++ .../checkers/RSAEncryptionCheckerTest.java | 33 +++++++++ 8 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionChecker.java create mode 100644 sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.htm create mode 100644 sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.json create mode 100644 sonar-keyware-plugins-java/src/test/files/RSAEncryptionRule.java create mode 100644 sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionCheckerTest.java diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicCodeChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicCodeChecker.java index ce02547..a8dfb04 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicCodeChecker.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicCodeChecker.java @@ -10,10 +10,7 @@ package com.keyware.sonar.java.rules.checkers; import org.sonar.check.Rule; import org.sonar.java.ast.visitors.SubscriptionVisitor; import org.sonar.plugins.java.api.tree.*; -import org.springframework.expression.EvaluationException; -import java.lang.reflect.Method; -import java.sql.ClientInfoStatus; import java.util.Collections; import java.util.List; diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java index b1abe56..8980daa 100644 --- a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadChecker.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ package com.keyware.sonar.java.rules.checkers; import org.sonar.check.Rule; diff --git a/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionChecker.java b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionChecker.java new file mode 100644 index 0000000..90aa573 --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionChecker.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +package com.keyware.sonar.java.rules.checkers; + +import org.sonar.check.Rule; +import org.sonar.java.ast.parser.ArgumentListTreeImpl; +import org.sonar.java.ast.visitors.SubscriptionVisitor; +import org.sonar.java.model.InternalSyntaxToken; +import org.sonar.java.model.expression.LiteralTreeImpl; +import org.sonar.plugins.java.api.tree.*; + +import java.util.Collections; +import java.util.List; + +/** + * TODO RSAEncryptionChecker + * + * @author RenFengJiang + * @date 2024/1/11 + */ +@Rule(key = "RSAEncryptionChecker") +public class RSAEncryptionChecker extends SubscriptionVisitor { + + @Override + public List nodesToVisit() { + /** + * Tree.Kind.METHOD:方法节点 + * Tree.Kind.BLOCK:方法的代码块节点 + * Tree.Kind.METHOD_INVOCATION: 方法的调用节点 + */ + return Collections.singletonList(Tree.Kind.METHOD_INVOCATION); + } + + @Override + public void visitNode(Tree tree) { + MethodInvocationTree methodInvocationTree = (MethodInvocationTree) tree; + ExpressionTree expressionTree = methodInvocationTree.methodSelect(); +// 获取到方法调用 + if(expressionTree instanceof MemberSelectExpressionTree){ + MemberSelectExpressionTree memberSelectExpressionTree = (MemberSelectExpressionTree) expressionTree; +// 判断是否符合标准 + if("Cipher".equals(memberSelectExpressionTree.expression().toString()) && "getInstance".equals(memberSelectExpressionTree.identifier().name())){ +// 获取参数列表 + Arguments arguments = methodInvocationTree.arguments(); + if(arguments instanceof ArgumentListTreeImpl){ +// 获取到参数列表 + ArgumentListTreeImpl argumentListTree = (ArgumentListTreeImpl) arguments; + for (ExpressionTree argument : argumentListTree) { + if(argument instanceof LiteralTreeImpl){ + LiteralTreeImpl literalTree = (LiteralTreeImpl) argument; +// 获取到其中的参数 + SyntaxToken syntaxToken = literalTree.token(); + if(syntaxToken instanceof InternalSyntaxToken){ + InternalSyntaxToken internalSyntaxToken = (InternalSyntaxToken) syntaxToken; +// 对参数进行判断判断是否符合要求 + if(!(internalSyntaxToken.text().startsWith("\"RSA") && internalSyntaxToken.text().contains("OAEPWithSHA-256AndMGF1Padding"))){ + context.reportIssue(this,tree,"使用RSA最优加密填充"); + } + } + } + } + } + } + } + } +} diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.htm b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.htm new file mode 100644 index 0000000..fbe4f2c --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.htm @@ -0,0 +1,9 @@ +

使用RSA最优加密填充

+

使用RSA加密算法时使用最优非对称加密填充

+
+
+
+

合规解决方案

+
+
+
diff --git a/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.json b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.json new file mode 100644 index 0000000..79848cb --- /dev/null +++ b/sonar-keyware-plugins-java/src/main/resources/org/sonar/l10n/java/rules/java/RSAEncryptionChecker.json @@ -0,0 +1,13 @@ +{ + "title": "使用RSA最优加密填充", + "type": "CODE_SMELL", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "28suo" + ], + "defaultSeverity": "Minor" +} \ No newline at end of file diff --git a/sonar-keyware-plugins-java/src/test/files/RSAEncryptionRule.java b/sonar-keyware-plugins-java/src/test/files/RSAEncryptionRule.java new file mode 100644 index 0000000..5a3713e --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/files/RSAEncryptionRule.java @@ -0,0 +1,30 @@ + + +public class RSAEncryptionRule { + public static void main(String[] args) throws Exception { + // 生成RSA密钥对 + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); + SecureRandom secureRandom = new SecureRandom(); + keyPairGenerator.initialize(2048, secureRandom); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + PublicKey publicKey = keyPair.getPublic(); + PrivateKey privateKey = keyPair.getPrivate(); + + // 待加密的数据 + String message = "Hello, RSA!"; + + // 使用公钥进行加密 + Cipher encryptCipher = Cipher.getInstance("OAEPWithAndPadding");// Noncompliant {{使用RSA最优加密填充}} + encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey); + byte[] encryptedBytes = encryptCipher.doFinal(message.getBytes()); + + // 使用私钥进行解密 + Cipher decryptCipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"); + decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); + byte[] decryptedBytes = decryptCipher.doFinal(encryptedBytes); + + // 输出结果 + System.out.println("加密后的数据:" + new String(encryptedBytes)); + System.out.println("解密后的数据:" + new String(decryptedBytes)); + } +} diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadCheckerTest.java index 5e2eb0e..74a8fa8 100644 --- a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadCheckerTest.java +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/DynamicLibraryLoadCheckerTest.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ package com.keyware.sonar.java.rules.checkers; import com.keyware.sonar.java.utils.FilesUtils; diff --git a/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionCheckerTest.java b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionCheckerTest.java new file mode 100644 index 0000000..36cd9db --- /dev/null +++ b/sonar-keyware-plugins-java/src/test/java/com/keyware/sonar/java/rules/checkers/RSAEncryptionCheckerTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 - 2024. KeyWare.Co.Ltd All rights reserved. + * 项目名称:Java 信息安全性设计准则 + * 项目描述:用于检查Java源代码的安全性设计准则的Sonarqube插件 + * 版权说明:本软件属北京关键科技股份有限公司所有,在未获得北京关键科技股份有限公司正式授权情况下,任何企业和个人,不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。 + */ +package com.keyware.sonar.java.rules.checkers; + +import com.keyware.sonar.java.utils.FilesUtils; +import org.junit.jupiter.api.Test; +import org.sonar.java.checks.verifier.CheckVerifier; + +/** + * TODO RSAEncryptionCheckerTest + * + * @author RenFengJiang + * @date 2024/1/11 + */ +public class RSAEncryptionCheckerTest { + @Test + void detected() { + RSAEncryptionChecker rule = new RSAEncryptionChecker(); + + // Verifies that the check will raise the adequate issues with the expected message. + // In the test file, lines which should raise an issue have been commented out + // by using the following syntax: "// Noncompliant {{EXPECTED_MESSAGE}}" + CheckVerifier.newVerifier() + .onFile("src/test/files/RSAEncryptionRule.java") + .withCheck(rule) + .withClassPath(FilesUtils.getClassPath("target/test-jars")) + .verifyIssues(); + } +}