diff --git a/pom.xml b/pom.xml
index 711ae28..3a768cf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
21
UTF-8
- 1.5.1
+ 2.0.0-SNAPSHOT
13.4.3.4290
25.8.0.112029
diff --git a/src/main/java/org/pqca/indexing/csharp/CSharpBuildType.java b/src/main/java/org/pqca/indexing/csharp/CSharpBuildType.java
new file mode 100644
index 0000000..0b31547
--- /dev/null
+++ b/src/main/java/org/pqca/indexing/csharp/CSharpBuildType.java
@@ -0,0 +1,26 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2025 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.indexing.csharp;
+
+import org.pqca.indexing.IBuildType;
+
+public enum CSharpBuildType implements IBuildType {
+ CSPROJ
+}
diff --git a/src/main/java/org/pqca/indexing/csharp/CSharpIndexService.java b/src/main/java/org/pqca/indexing/csharp/CSharpIndexService.java
new file mode 100644
index 0000000..541aebf
--- /dev/null
+++ b/src/main/java/org/pqca/indexing/csharp/CSharpIndexService.java
@@ -0,0 +1,72 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.indexing.csharp;
+
+import jakarta.annotation.Nonnull;
+import java.io.File;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.pqca.indexing.IBuildType;
+import org.pqca.indexing.IndexingService;
+import org.pqca.progress.IProgressDispatcher;
+
+public final class CSharpIndexService extends IndexingService {
+
+ public CSharpIndexService(@Nonnull File baseDirectory) {
+ this(null, baseDirectory);
+ }
+
+ public CSharpIndexService(
+ @Nullable IProgressDispatcher progressDispatcher, @Nonnull File baseDirectory) {
+ super(progressDispatcher, baseDirectory, "cs", ".cs");
+ this.setExcludePatterns(null);
+ }
+
+ public void setExcludePatterns(@Nullable List patterns) {
+ if (patterns == null) {
+ super.setExcludePatterns(List.of("tests/", "Tests$"));
+ } else {
+ super.setExcludePatterns(patterns);
+ }
+ }
+
+ @Override
+ public boolean isModule(@Nonnull File directory) {
+ if (!directory.isDirectory()) {
+ return false;
+ }
+
+ final File file = new File(directory, directory.getName() + ".csproj");
+ return file.exists() && file.isFile();
+ }
+
+ @Override
+ @Nullable public IBuildType getMainBuildTypeFromModuleDirectory(@Nonnull File directory) {
+ if (!directory.isDirectory()) {
+ return null;
+ }
+ // csproj
+ final File csProjFile = new File(directory, directory.getName() + ".csproj");
+ if (csProjFile.exists() && csProjFile.isFile()) {
+ return CSharpBuildType.CSPROJ;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/org/pqca/scanning/Language.java b/src/main/java/org/pqca/scanning/Language.java
index e335af3..84dc8cb 100644
--- a/src/main/java/org/pqca/scanning/Language.java
+++ b/src/main/java/org/pqca/scanning/Language.java
@@ -22,5 +22,6 @@
public enum Language {
JAVA,
PYTHON,
- GO
+ GO,
+ CSHARP
}
diff --git a/src/main/java/org/pqca/scanning/csharp/CSharpDetectionCollectionRule.java b/src/main/java/org/pqca/scanning/csharp/CSharpDetectionCollectionRule.java
new file mode 100644
index 0000000..532a682
--- /dev/null
+++ b/src/main/java/org/pqca/scanning/csharp/CSharpDetectionCollectionRule.java
@@ -0,0 +1,47 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2024 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.scanning.csharp;
+
+import com.ibm.engine.detection.Finding;
+import com.ibm.engine.language.csharp.CSharpCheck;
+import com.ibm.engine.language.csharp.CSharpScanContext;
+import com.ibm.engine.language.csharp.CSharpSymbol;
+import com.ibm.engine.language.csharp.tree.CSharpTree;
+import com.ibm.mapper.model.INode;
+import com.ibm.plugin.rules.CSharpInventoryRule;
+import jakarta.annotation.Nonnull;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class CSharpDetectionCollectionRule extends CSharpInventoryRule {
+ private final Consumer> handler;
+
+ public CSharpDetectionCollectionRule(@Nonnull Consumer> findingConsumer) {
+ this.handler = findingConsumer;
+ }
+
+ @Override
+ public void update(
+ @Nonnull Finding finding) {
+ super.update(finding);
+ final List nodes = csharpTranslationProcess.initiate(finding.detectionStore());
+ handler.accept(nodes);
+ }
+}
diff --git a/src/main/java/org/pqca/scanning/csharp/CSharpScannerService.java b/src/main/java/org/pqca/scanning/csharp/CSharpScannerService.java
new file mode 100644
index 0000000..7a5d9d8
--- /dev/null
+++ b/src/main/java/org/pqca/scanning/csharp/CSharpScannerService.java
@@ -0,0 +1,95 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2026 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.scanning.csharp;
+
+import com.ibm.engine.language.csharp.CSharpCheck;
+import com.ibm.plugin.CryptoCSharpSensor;
+import jakarta.annotation.Nonnull;
+import jakarta.annotation.Nullable;
+import java.io.File;
+import java.util.Collection;
+import java.util.List;
+import org.pqca.errors.ClientDisconnected;
+import org.pqca.indexing.ProjectModule;
+import org.pqca.progress.IProgressDispatcher;
+import org.pqca.progress.ProgressMessage;
+import org.pqca.progress.ProgressMessageType;
+import org.pqca.scanning.CBOM;
+import org.pqca.scanning.ScanResultDTO;
+import org.pqca.scanning.ScannerService;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.sensor.SensorContext;
+import org.sonar.api.batch.sensor.internal.SensorContextTester;
+
+public final class CSharpScannerService extends ScannerService {
+
+ public CSharpScannerService(@Nonnull File projectDirectory) {
+ this(null, projectDirectory);
+ }
+
+ public CSharpScannerService(
+ @Nullable IProgressDispatcher progressDispatcher, @Nonnull File projectDirectory) {
+ super(progressDispatcher, projectDirectory);
+ }
+
+ @Override
+ public @Nonnull ScanResultDTO scan(@Nonnull List index)
+ throws ClientDisconnected {
+ LOGGER.info("Start scanning {} C# projects", index.size());
+
+ long scanTimeStart = System.currentTimeMillis();
+ int counter = 1;
+ int numberOfScannedLines = 0;
+ int numberOfScannedFiles = 0;
+
+ CSharpCheck visitor = new CSharpDetectionCollectionRule(this);
+ Collection checks = List.of(visitor);
+ final SensorContextTester sensorContext = SensorContextTester.create(projectDirectory);
+ // C# scanner (CryptoCSharpSensor) reads files from context
+ index.forEach(project -> project.inputFileList().forEach(sensorContext.fileSystem()::add));
+
+ for (ProjectModule project : index) {
+ numberOfScannedFiles += project.inputFileList().size();
+ numberOfScannedLines +=
+ project.inputFileList().stream().mapToInt(InputFile::lines).sum();
+
+ final String projectStr =
+ project.identifier() + " (" + counter + "/" + index.size() + ")";
+ if (this.progressDispatcher != null) {
+ this.progressDispatcher.send(
+ new ProgressMessage(
+ ProgressMessageType.LABEL, "Scanning C# project " + projectStr));
+ }
+ LOGGER.info("Scanning C# project {}", projectStr);
+
+ CryptoCSharpSensor.execute((SensorContext) sensorContext, checks);
+
+ counter += 1;
+ }
+ LOGGER.info("Scanned {} C# projects", index.size());
+
+ return new ScanResultDTO(
+ scanTimeStart,
+ System.currentTimeMillis(),
+ numberOfScannedLines,
+ numberOfScannedFiles,
+ this.getBOM().map(CBOM::new).orElse(null));
+ }
+}
diff --git a/src/main/java/org/pqca/scanning/go/GoScannerService.java b/src/main/java/org/pqca/scanning/go/GoScannerService.java
index 29b5a3d..42f374e 100644
--- a/src/main/java/org/pqca/scanning/go/GoScannerService.java
+++ b/src/main/java/org/pqca/scanning/go/GoScannerService.java
@@ -134,7 +134,6 @@ public List all() {
return this.checks;
}
- @SuppressWarnings("null")
public RuleKey ruleKey(GoCheck check) {
return RuleKey.of("sonar-cryptography", "go-rule");
}
diff --git a/src/test/java/org/pqca/indexing/CSharpIndexServiceTest.java b/src/test/java/org/pqca/indexing/CSharpIndexServiceTest.java
new file mode 100644
index 0000000..df57b28
--- /dev/null
+++ b/src/test/java/org/pqca/indexing/CSharpIndexServiceTest.java
@@ -0,0 +1,52 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2025 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.indexing;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertThat;
+
+import java.io.File;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.pqca.errors.ClientDisconnected;
+import org.pqca.indexing.csharp.CSharpIndexService;
+
+class CSharpIndexServiceTest {
+ @Test
+ void testDefaultExclusion() throws ClientDisconnected {
+ final CSharpIndexService csharpIndexService =
+ new CSharpIndexService(new File("src/test/testdata/csharp/dotnet"));
+ final List projectModules = csharpIndexService.index(null);
+ assertThat(projectModules).hasSize(1);
+ assertThat(projectModules.getFirst().identifier()).isEqualTo("");
+ assertThat(projectModules.getFirst().inputFileList()).hasSize(12);
+ }
+
+ @Test
+ void testExclusion() throws ClientDisconnected {
+ final CSharpIndexService csharpIndexService =
+ new CSharpIndexService(new File("src/test/testdata/csharp/dotnet"));
+ csharpIndexService.setExcludePatterns(List.of("AES"));
+ final List projectModules = csharpIndexService.index(null);
+ assertThat(projectModules).hasSize(1);
+ assertThat(projectModules.getFirst().identifier()).isEqualTo("");
+ assertThat(projectModules.getFirst().inputFileList()).hasSize(10);
+ }
+}
diff --git a/src/test/java/org/pqca/indexing/GoIndexServiceTest.java b/src/test/java/org/pqca/indexing/GoIndexServiceTest.java
index 3611860..5cb7f30 100644
--- a/src/test/java/org/pqca/indexing/GoIndexServiceTest.java
+++ b/src/test/java/org/pqca/indexing/GoIndexServiceTest.java
@@ -32,11 +32,21 @@ class GoIndexServiceTest {
@Test
void testDefaultExclusion() throws ClientDisconnected {
final GoIndexService goIndexService =
- new GoIndexService(new File("src/test/testdata/go/simple"));
+ new GoIndexService(new File("src/test/testdata/go/gocrypto"));
final List projectModules = goIndexService.index(null);
assertThat(projectModules).hasSize(1);
- assertThat(projectModules.getFirst().inputFileList())
- .extracting(Object::toString)
- .containsExactlyInAnyOrder("go.mod", "module1/file.go");
+ assertThat(projectModules.getFirst().identifier()).isEqualTo("");
+ assertThat(projectModules.getFirst().inputFileList()).hasSize(36);
+ }
+
+ @Test
+ void testCustomExclusion() throws ClientDisconnected {
+ final GoIndexService goIndexService =
+ new GoIndexService(new File("src/test/testdata/go/gocrypto"));
+ goIndexService.setExcludePatterns(List.of("RSA"));
+ final List projectModules = goIndexService.index(null);
+ assertThat(projectModules).hasSize(1);
+ assertThat(projectModules.getFirst().identifier()).isEqualTo("");
+ assertThat(projectModules.getFirst().inputFileList()).hasSize(31);
}
}
diff --git a/src/test/java/org/pqca/scanning/CSharpScannerServiceTest.java b/src/test/java/org/pqca/scanning/CSharpScannerServiceTest.java
new file mode 100644
index 0000000..0a2c471
--- /dev/null
+++ b/src/test/java/org/pqca/scanning/CSharpScannerServiceTest.java
@@ -0,0 +1,84 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2025 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.scanning;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.pqca.errors.ClientDisconnected;
+import org.pqca.indexing.ProjectModule;
+import org.pqca.indexing.csharp.CSharpIndexService;
+import org.pqca.scanning.csharp.CSharpScannerService;
+import org.pqca.utils.AssertableCBOM;
+
+class CSharpScannerServiceTest {
+
+ @Test
+ void test() throws ClientDisconnected {
+ // indexing
+ final File projectDirectory =
+ new File("/Users/san/oss/sonar-cryptography/csharp/src/test/files");
+ final CSharpIndexService cSharpIndexService = new CSharpIndexService(projectDirectory);
+ final List cSharpModules = cSharpIndexService.index(null);
+ assertThat(cSharpModules).hasSize(1);
+ final ProjectModule projectModule = cSharpModules.getFirst();
+ assertThat(projectModule.inputFileList()).hasSize(12);
+ // scanning
+ final CSharpScannerService cSharpScannerService =
+ new CSharpScannerService(projectDirectory);
+ ScanResultDTO scanResult = cSharpScannerService.scan(cSharpModules);
+
+ // check - 21 unique cryptographic assets with 27 total occurrences
+ AssertableCBOM assertableCBOM = new AssertableCBOM(scanResult.cbom());
+ assertThat(scanResult.cbom().cycloneDXbom().getComponents()).hasSize(21);
+ assertableCBOM.hasNumberOfDetections(27);
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "SHA256", "rules/detection/dotnet/DotNetSHATestFile.cs", 4))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "AES256-CBC-PKCS7",
+ "rules/detection/dotnet/DotNetAESPropertyTestFile.cs",
+ 7))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "HMAC-SHA256", "rules/detection/dotnet/DotNetHMACTestFile.cs", 4))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "RSA", "rules/detection/dotnet/DotNetRSATestFile.cs", 3))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "PBKDF2",
+ "rules/detection/dotnet/DotNetRfc2898DeriveBytesTestFile.cs",
+ 4))
+ .isTrue();
+ }
+}
diff --git a/src/test/java/org/pqca/scanning/GoScannerServiceTest.java b/src/test/java/org/pqca/scanning/GoScannerServiceTest.java
new file mode 100644
index 0000000..010e436
--- /dev/null
+++ b/src/test/java/org/pqca/scanning/GoScannerServiceTest.java
@@ -0,0 +1,90 @@
+/*
+ * CBOMkit-lib
+ * Copyright (C) 2025 PQCA
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.pqca.scanning;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.pqca.errors.ClientDisconnected;
+import org.pqca.indexing.ProjectModule;
+import org.pqca.indexing.go.GoIndexService;
+import org.pqca.scanning.go.GoScannerService;
+import org.pqca.utils.AssertableCBOM;
+
+class GoScannerServiceTest {
+
+ @Test
+ void test() throws ClientDisconnected {
+ // indexing
+ final File projectDirectory = new File("src/test/testdata/go/gocrypto");
+ final GoIndexService goIndexService = new GoIndexService(projectDirectory);
+ final List goModules = goIndexService.index(null);
+ assertThat(goModules).hasSize(1);
+ final ProjectModule projectModule = goModules.getFirst();
+ assertThat(projectModule.inputFileList()).isNotEmpty();
+ // scanning
+ final GoScannerService goScannerService = new GoScannerService(projectDirectory);
+ ScanResultDTO scanResult = goScannerService.scan(goModules);
+
+ // check - verify cryptographic assets are detected
+ AssertableCBOM assertableCBOM = new AssertableCBOM(scanResult.cbom());
+ assertThat(scanResult.cbom().cycloneDXbom().getComponents()).hasSize(27);
+ assertableCBOM.hasNumberOfDetections(69);
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "SHA256",
+ "src/test/testdata/go/gocrypto/GoCryptoSHA256TestFile.go",
+ 10))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "AES-GCM",
+ "src/test/testdata/go/gocrypto/GoCryptoAESTestFile.go",
+ 18))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "RSA-2048",
+ "src/test/testdata/go/gocrypto/GoCryptoRSATestFile.go",
+ 10))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "HMAC-SHA256",
+ "src/test/testdata/go/gocrypto/GoCryptoHMACTestFile.go",
+ 11))
+ .isTrue();
+
+ assertThat(
+ assertableCBOM.hasDetectionWithNameAt(
+ "PBKDF2",
+ "src/test/testdata/go/gocrypto/GoCryptoPBKDF2TestFile.go",
+ 15))
+ .isTrue();
+ }
+}
+
+// Made with Bob
diff --git a/src/test/testdata/csharp/dotnet/DotNetAESPropertyTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetAESPropertyTestFile.cs
new file mode 100644
index 0000000..a97e1ad
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetAESPropertyTestFile.cs
@@ -0,0 +1,19 @@
+using System.Security.Cryptography;
+
+public class DotNetAESPropertyTest
+{
+ public void TestAesWithProperties()
+ {
+ var aes = Aes.Create();
+ aes.Mode = CipherMode.CBC;
+ aes.KeySize = 256;
+ aes.Padding = PaddingMode.PKCS7;
+ }
+
+ public void TestAesManagedWithMode()
+ {
+ var aes = new AesManaged();
+ aes.Mode = CipherMode.ECB;
+ aes.KeySize = 128;
+ }
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetAESTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetAESTestFile.cs
new file mode 100755
index 0000000..6f24227
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetAESTestFile.cs
@@ -0,0 +1,14 @@
+using System.Security.Cryptography;
+
+public class DotNetAESTest
+{
+ public void TestAesCreate()
+ {
+ var aes = Aes.Create(); // Noncompliant
+ }
+
+ public void TestAesManaged()
+ {
+ var aes = new AesManaged(); // Noncompliant
+ }
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetDESTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetDESTestFile.cs
new file mode 100755
index 0000000..7e53f08
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetDESTestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetDESTest {
+ public void TestDesCreate() { var des = DES.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetDSATestFile.cs b/src/test/testdata/csharp/dotnet/DotNetDSATestFile.cs
new file mode 100755
index 0000000..63e24c9
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetDSATestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetDSATest {
+ public void TestDsaCreate() { var dsa = DSA.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetECDiffieHellmanTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetECDiffieHellmanTestFile.cs
new file mode 100755
index 0000000..2c91853
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetECDiffieHellmanTestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetECDiffieHellmanTest {
+ public void TestECDHCreate() { var ecdh = ECDiffieHellman.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetECDsaTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetECDsaTestFile.cs
new file mode 100755
index 0000000..addadc0
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetECDsaTestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetECDsaTest {
+ public void TestECDsaCreate() { var ecdsa = ECDsa.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetHMACTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetHMACTestFile.cs
new file mode 100755
index 0000000..b652359
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetHMACTestFile.cs
@@ -0,0 +1,8 @@
+using System.Security.Cryptography;
+public class DotNetHMACTest {
+ public void TestHmacSha1() { var h = new HMACSHA1(); } // Noncompliant
+ public void TestHmacSha256() { var h = new HMACSHA256(); } // Noncompliant
+ public void TestHmacSha384() { var h = new HMACSHA384(); } // Noncompliant
+ public void TestHmacSha512() { var h = new HMACSHA512(); } // Noncompliant
+ public void TestHmacMd5() { var h = new HMACMD5(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetRC2TestFile.cs b/src/test/testdata/csharp/dotnet/DotNetRC2TestFile.cs
new file mode 100755
index 0000000..ac73952
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetRC2TestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetRC2Test {
+ public void TestRc2Create() { var rc2 = RC2.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetRSATestFile.cs b/src/test/testdata/csharp/dotnet/DotNetRSATestFile.cs
new file mode 100755
index 0000000..1478482
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetRSATestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetRSATest {
+ public void TestRsaCreate() { var rsa = RSA.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetRfc2898DeriveBytesTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetRfc2898DeriveBytesTestFile.cs
new file mode 100755
index 0000000..eefd474
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetRfc2898DeriveBytesTestFile.cs
@@ -0,0 +1,6 @@
+using System.Security.Cryptography;
+public class DotNetRfc2898DeriveBytesTest {
+ public void TestPbkdf2() {
+ var kdf = new Rfc2898DeriveBytes("password", new byte[16], 10000, HashAlgorithmName.SHA256); // Noncompliant
+ }
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetSHATestFile.cs b/src/test/testdata/csharp/dotnet/DotNetSHATestFile.cs
new file mode 100755
index 0000000..9ab3b53
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetSHATestFile.cs
@@ -0,0 +1,8 @@
+using System.Security.Cryptography;
+public class DotNetSHATest {
+ public void TestSha1Create() { var h = SHA1.Create(); } // Noncompliant
+ public void TestSha256Create() { var h = SHA256.Create(); } // Noncompliant
+ public void TestSha384Create() { var h = SHA384.Create(); } // Noncompliant
+ public void TestSha512Create() { var h = SHA512.Create(); } // Noncompliant
+ public void TestMd5Create() { var h = MD5.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/dotnet/DotNetTripleDESTestFile.cs b/src/test/testdata/csharp/dotnet/DotNetTripleDESTestFile.cs
new file mode 100755
index 0000000..9c85d16
--- /dev/null
+++ b/src/test/testdata/csharp/dotnet/DotNetTripleDESTestFile.cs
@@ -0,0 +1,4 @@
+using System.Security.Cryptography;
+public class DotNetTripleDESTest {
+ public void TestTripleDesCreate() { var des = TripleDES.Create(); } // Noncompliant
+}
diff --git a/src/test/testdata/csharp/module/module.cs b/src/test/testdata/csharp/module/module.cs
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/testdata/csharp/module/module.csproj b/src/test/testdata/csharp/module/module.csproj
new file mode 100644
index 0000000..e69de29
diff --git a/src/test/testdata/go/gocrypto/118c1b0b6b7b456b8b205c3fbd6c7913/18327813402862104194/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/118c1b0b6b7b456b8b205c3fbd6c7913/18327813402862104194/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/118c1b0b6b7b456b8b205c3fbd6c7913/18327813402862104194/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/3d045eab77ce43a68a8e7de0f4e1f055/14751112134127390757/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/3d045eab77ce43a68a8e7de0f4e1f055/14751112134127390757/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/3d045eab77ce43a68a8e7de0f4e1f055/14751112134127390757/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/502e370baa53434894cf982ddda128c8/18138029745714173922/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/502e370baa53434894cf982ddda128c8/18138029745714173922/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/502e370baa53434894cf982ddda128c8/18138029745714173922/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/5b222988e9754ef18678431de7343c7d/14909100671640466717/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/5b222988e9754ef18678431de7343c7d/14909100671640466717/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/5b222988e9754ef18678431de7343c7d/14909100671640466717/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/85b8c309f1fc458e8ab4b2111ae8062c/11401187076560982630/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/85b8c309f1fc458e8ab4b2111ae8062c/11401187076560982630/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/85b8c309f1fc458e8ab4b2111ae8062c/11401187076560982630/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/9b6654c27d384ae8b20b4b53ded88455/13814205431856933034/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/9b6654c27d384ae8b20b4b53ded88455/13814205431856933034/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/9b6654c27d384ae8b20b4b53ded88455/13814205431856933034/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/GoCryptoAESGCMEncryptTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoAESGCMEncryptTestFile.go
new file mode 100644
index 0000000..34b8569
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoAESGCMEncryptTestFile.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ crand "crypto/rand"
+ "encoding/base64"
+ "io"
+)
+
+// Encrypt encrypts "data" with the specified "key" (must be valid 32 char AES key).
+//
+// This method uses AES-256-GCM block cypher mode.
+func Encrypt(data []byte, key string) (string, error) {
+ block, err := aes.NewCipher([]byte(key)) // Noncompliant {{(AuthenticatedEncryption) AES-GCM}}
+ if err != nil {
+ return "", err
+ }
+
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ return "", err
+ }
+
+ nonce := make([]byte, gcm.NonceSize())
+
+ // populates the nonce with a cryptographically secure random sequence
+ if _, err := io.ReadFull(crand.Reader, nonce); err != nil {
+ return "", err
+ }
+
+ cipherByte := gcm.Seal(nonce, nonce, data, nil)
+
+ result := base64.StdEncoding.EncodeToString(cipherByte)
+
+ return result, nil
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoAESGCMWithNonceSizeTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoAESGCMWithNonceSizeTestFile.go
new file mode 100644
index 0000000..02ede48
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoAESGCMWithNonceSizeTestFile.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+)
+
+// AES-GCM Decryption with custom nonce size
+func AesGcmDecrypt(cipherText, cek, nonce, authTag, aad []byte) ([]byte, error) {
+ cipherTextWithAuthTag := append(cipherText, authTag...)
+
+ block, err := aes.NewCipher(cek) // Noncompliant {{(AuthenticatedEncryption) AES-GCM}}
+ if err != nil {
+ return nil, err
+ }
+ aesgcm, err := cipher.NewGCMWithNonceSize(block, len(nonce))
+ if err != nil {
+ return nil, err
+ }
+ plainText, err := aesgcm.Open(nil, nonce, cipherTextWithAuthTag, aad)
+ if err != nil {
+ return nil, err
+ }
+ return plainText, nil
+}
+
+// AES-GCM Encryption with custom nonce size
+func AesGcmEncrypt(plainText, cek, nonce, aad []byte) ([]byte, []byte, error) {
+ _len := len(plainText)
+ block, err := aes.NewCipher(cek) // Noncompliant {{(AuthenticatedEncryption) AES-GCM}}
+ if err != nil {
+ return nil, nil, err
+ }
+
+ aesGcm, err := cipher.NewGCMWithNonceSize(block, len(nonce))
+ if err != nil {
+ return nil, nil, err
+ }
+
+ cipherText := aesGcm.Seal(nil, nonce, plainText, aad)
+ return cipherText[:_len], cipherText[_len:], nil
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoAESTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoAESTestFile.go
new file mode 100644
index 0000000..582ec2d
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoAESTestFile.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/rand"
+ "io"
+)
+
+func main() {
+ // Generate a random 32-byte key (AES-256)
+ key := make([]byte, 32)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ panic(err)
+ }
+
+ // Create a new AES cipher block - this should be detected
+ block, err := aes.NewCipher(key) // Noncompliant {{(AuthenticatedEncryption) AES256-GCM}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Create a GCM mode cipher
+ gcm, err := cipher.NewGCM(block)
+ if err != nil {
+ panic(err)
+ }
+
+ // Example plaintext
+ plaintext := []byte("Hello, World!")
+
+ // Generate a random nonce
+ nonce := make([]byte, gcm.NonceSize())
+ if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+ panic(err)
+ }
+
+ // Encrypt
+ ciphertext := gcm.Seal(nonce, nonce, plaintext, nil)
+ _ = ciphertext
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoDESTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoDESTestFile.go
new file mode 100644
index 0000000..bca1166
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoDESTestFile.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "crypto/des"
+)
+
+func main() {
+ key := make([]byte, 8)
+ block, err := des.NewCipher(key) // Noncompliant {{(BlockCipher) DES64}}
+ if err != nil {
+ panic(err)
+ }
+ _ = block
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoDSATestFile.go b/src/test/testdata/go/gocrypto/GoCryptoDSATestFile.go
new file mode 100644
index 0000000..ad5a442
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoDSATestFile.go
@@ -0,0 +1,34 @@
+package main
+
+import (
+ "crypto/dsa"
+ "crypto/rand"
+)
+
+func main() {
+ // Generate DSA parameters with L2048N256 size
+ params := new(dsa.Parameters)
+ err := dsa.GenerateParameters(params, rand.Reader, dsa.L2048N256)
+ if err != nil {
+ panic(err)
+ }
+
+ // Generate a DSA key pair
+ privateKey := new(dsa.PrivateKey)
+ privateKey.Parameters = *params
+ err = dsa.GenerateKey(privateKey, rand.Reader) // Noncompliant {{(Signature) DSA}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Sign a hash
+ hash := []byte("test message hash")
+ r, s, err := dsa.Sign(rand.Reader, privateKey, hash) // Noncompliant {{(Signature) DSA}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Verify the signature
+ valid := dsa.Verify(&privateKey.PublicKey, hash, r, s) // Noncompliant {{(Signature) DSA}}
+ _ = valid
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDHNewPrivateKeyTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDHNewPrivateKeyTestFile.go
new file mode 100644
index 0000000..8f34493
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDHNewPrivateKeyTestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/ecdh"
+)
+
+func main() {
+ // Test NewPrivateKey with P256 curve
+ curve := ecdh.P256() // Noncompliant {{(KeyAgreement) ECDH}}
+
+ // Create a private key from raw bytes (32 bytes for P256)
+ privateKeyBytes := make([]byte, 32)
+ privateKey, err := curve.NewPrivateKey(privateKeyBytes)
+ if err != nil {
+ panic(err)
+ }
+
+ _ = privateKey
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDHNewPublicKeyTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDHNewPublicKeyTestFile.go
new file mode 100644
index 0000000..7c8e812
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDHNewPublicKeyTestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/ecdh"
+)
+
+func main() {
+ // Test NewPublicKey with X25519 curve
+ curve := ecdh.X25519() // Noncompliant {{(KeyAgreement) ECDH}}
+
+ // Create a public key from raw bytes (32 bytes for X25519)
+ publicKeyBytes := make([]byte, 32)
+ publicKey, err := curve.NewPublicKey(publicKeyBytes)
+ if err != nil {
+ panic(err)
+ }
+
+ _ = publicKey
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDHTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDHTestFile.go
new file mode 100644
index 0000000..1bbd475
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDHTestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/ecdh"
+ "crypto/rand"
+)
+
+func main() {
+ // Get the P256 curve
+ curve := ecdh.P256() // Noncompliant {{(KeyAgreement) ECDH}}
+
+ // Generate a key pair
+ privateKey, err := curve.GenerateKey(rand.Reader)
+ if err != nil {
+ panic(err)
+ }
+
+ _ = privateKey
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDSASignASN1TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDSASignASN1TestFile.go
new file mode 100644
index 0000000..c44e6f6
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDSASignASN1TestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+)
+
+func main() {
+ // Sign the hash using SignASN1
+ privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) // Noncompliant {{(Signature) ECDSA}}
+
+ var hash []byte
+ sig, err := ecdsa.SignASN1(rand.Reader, privateKey, hash) // Noncompliant {{(Signature) ECDSA}}
+ if err != nil {
+ panic(err)
+ }
+ _ = sig
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDSATestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDSATestFile.go
new file mode 100644
index 0000000..003dfa1
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDSATestFile.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+)
+
+func main() {
+ // Generate an ECDSA key pair using P-256 curve
+ privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) // Noncompliant {{(Signature) ECDSA}}
+ if err != nil {
+ panic(err)
+ }
+ _ = privateKey
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoECDSAVerifyASN1TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoECDSAVerifyASN1TestFile.go
new file mode 100644
index 0000000..583d7b2
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoECDSAVerifyASN1TestFile.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "crypto/rand"
+)
+
+func main() {
+ // Verify the signature using VerifyASN1
+ privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) // Noncompliant {{(Signature) ECDSA}}
+ if err != nil {
+ panic(err)
+ }
+
+ var publicKey = &privateKey.PublicKey
+
+ var hash []byte
+ var sig []byte
+ valid := ecdsa.VerifyASN1(publicKey, hash, sig) // Noncompliant {{(Signature) ECDSA}}
+ _ = valid
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoEd25519SignTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoEd25519SignTestFile.go
new file mode 100644
index 0000000..6d54234
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoEd25519SignTestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/ed25519"
+ "crypto/rand"
+)
+
+func main() {
+ // Generate an Ed25519 key pair
+ _, priv, err := ed25519.GenerateKey(rand.Reader) // Noncompliant {{(Signature) Ed25519}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Sign a message
+ message := []byte("test message")
+ sig := ed25519.Sign(priv, message) // Noncompliant {{(Signature) Ed25519}}
+ _ = sig
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoEd25519TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoEd25519TestFile.go
new file mode 100644
index 0000000..9a76caa
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoEd25519TestFile.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+ "crypto/ed25519"
+ "crypto/rand"
+)
+
+func main() {
+ // GenerateKey - generates a public/private key pair
+ _, _, err := ed25519.GenerateKey(rand.Reader) // Noncompliant {{(Signature) Ed25519}}
+ if err != nil {
+ panic(err)
+ }
+
+ // NewKeyFromSeed - creates a private key from seed
+ seed := make([]byte, ed25519.SeedSize)
+ _ = ed25519.NewKeyFromSeed(seed) // Noncompliant {{(Signature) Ed25519}}
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoEd25519VerifyTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoEd25519VerifyTestFile.go
new file mode 100644
index 0000000..f7e554f
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoEd25519VerifyTestFile.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "crypto/ed25519"
+ "crypto/rand"
+)
+
+func main() {
+ // Generate an Ed25519 key pair
+ pub, _, err := ed25519.GenerateKey(rand.Reader) // Noncompliant {{(Signature) Ed25519}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Verify a signature
+ var message []byte
+ var sig []byte
+ valid := ed25519.Verify(pub, message, sig) // Noncompliant {{(Signature) Ed25519}}
+ _ = valid
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoEllipticTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoEllipticTestFile.go
new file mode 100644
index 0000000..72177be
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoEllipticTestFile.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "crypto/elliptic"
+ "fmt"
+)
+
+func main() {
+ // Test P-224 curve
+ p224 := elliptic.P224()
+ fmt.Println("P-224:", p224.Params().Name)
+
+ // Test P-256 curve
+ p256 := elliptic.P256()
+ fmt.Println("P-256:", p256.Params().Name)
+
+ // Test P-384 curve
+ p384 := elliptic.P384()
+ fmt.Println("P-384:", p384.Params().Name)
+
+ // Test P-521 curve
+ p521 := elliptic.P521()
+ fmt.Println("P-521:", p521.Params().Name)
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoHKDFExpandTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoHKDFExpandTestFile.go
new file mode 100644
index 0000000..83c0710
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoHKDFExpandTestFile.go
@@ -0,0 +1,19 @@
+package main
+
+import (
+ "crypto/sha256"
+ "golang.org/x/crypto/hkdf"
+)
+
+func main() {
+ secret := []byte("secret")
+ salt := []byte("salt")
+ info := []byte("info")
+
+ // HKDF Extract step
+ prk := hkdf.Extract(sha256.New, secret, salt)
+
+ // HKDF Expand step
+ reader := hkdf.Expand(sha256.New, prk, info, 32) // Noncompliant {{(KeyDerivationFunction) HKDF-SHA256}}
+ _ = reader
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoHKDFTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoHKDFTestFile.go
new file mode 100644
index 0000000..019751d
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoHKDFTestFile.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "crypto/sha256"
+ "golang.org/x/crypto/hkdf"
+)
+
+func main() {
+ secret := []byte("secret")
+ salt := []byte("salt")
+ info := []byte("info")
+
+ // HKDF Key derivation
+ reader := hkdf.New(sha256.New, secret, salt, info) // Noncompliant {{(KeyDerivationFunction) HKDF-SHA256}}
+ _ = reader
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoHMACTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoHMACTestFile.go
new file mode 100644
index 0000000..3f8d4a8
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoHMACTestFile.go
@@ -0,0 +1,14 @@
+package main
+
+import (
+ "crypto/hmac"
+ "crypto/sha256"
+ "fmt"
+)
+
+func main() {
+ key := []byte("secret-key")
+ h := hmac.New(sha256.New, key) // Noncompliant {{(Mac) HMAC-SHA256}}
+ h.Write([]byte("hello"))
+ fmt.Printf("%x\n", h.Sum(nil))
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoMD5TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoMD5TestFile.go
new file mode 100644
index 0000000..56b8b13
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoMD5TestFile.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "crypto/md5"
+ "fmt"
+)
+
+func main() {
+ h := md5.New() // Noncompliant {{(MessageDigest) MD5}}
+ h.Write([]byte("hello"))
+ sum := h.Sum(nil)
+ fmt.Printf("%x\n", sum)
+
+ // Also test md5.Sum directly
+ checksum := md5.Sum([]byte("data")) // Noncompliant {{(MessageDigest) MD5}}
+ fmt.Printf("%x\n", checksum)
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoMLKEM1024TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoMLKEM1024TestFile.go
new file mode 100644
index 0000000..38b4031
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoMLKEM1024TestFile.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "crypto/mlkem"
+)
+
+func main() {
+ // Generate an ML-KEM-1024 decapsulation key
+ dk, err := mlkem.GenerateKey1024() // Noncompliant {{(KeyEncapsulationMechanism) ML-KEM-1024}}
+ if err != nil {
+ panic(err)
+ }
+
+ _ = dk
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoMLKEMNewDecapsulationKeyTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoMLKEMNewDecapsulationKeyTestFile.go
new file mode 100644
index 0000000..2b2f972
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoMLKEMNewDecapsulationKeyTestFile.go
@@ -0,0 +1,16 @@
+package main
+
+import (
+ "crypto/mlkem"
+)
+
+func main() {
+ // Create an ML-KEM-768 decapsulation key from a seed (SeedSize = 64)
+ seed := make([]byte, 64)
+ dk, err := mlkem.NewDecapsulationKey768(seed) // Noncompliant {{(KeyEncapsulationMechanism) ML-KEM-768}}
+ if err != nil {
+ panic(err)
+ }
+
+ _ = dk
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoMLKEMTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoMLKEMTestFile.go
new file mode 100644
index 0000000..ea84cfe
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoMLKEMTestFile.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "crypto/mlkem"
+)
+
+func main() {
+ // Generate an ML-KEM-768 decapsulation key
+ dk, err := mlkem.GenerateKey768() // Noncompliant {{(KeyEncapsulationMechanism) ML-KEM-768}}
+ if err != nil {
+ panic(err)
+ }
+
+ _ = dk
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoPBKDF2StdlibTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoPBKDF2StdlibTestFile.go
new file mode 100644
index 0000000..9d63628
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoPBKDF2StdlibTestFile.go
@@ -0,0 +1,18 @@
+package main
+
+import (
+ "crypto/pbkdf2"
+ "crypto/sha256"
+)
+
+func main() {
+ salt := make([]byte, 16)
+
+ // PBKDF2 Key derivation using stdlib API (Go 1.24+)
+ key, err := pbkdf2.Key(sha256.New, "password", salt, 600000, 32) // Noncompliant {{(PasswordBasedKeyDerivationFunction) PBKDF2-SHA256}}
+ if err != nil {
+ panic(err)
+ }
+
+ _ = key
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoPBKDF2TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoPBKDF2TestFile.go
new file mode 100644
index 0000000..bfc157a
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoPBKDF2TestFile.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "crypto/sha256"
+ "golang.org/x/crypto/pbkdf2"
+)
+
+func main() {
+ password := []byte("password")
+ salt := []byte("salt")
+ iterations := 10000
+ keyLen := 32
+
+ // PBKDF2 Key derivation
+ key := pbkdf2.Key(password, salt, iterations, keyLen, sha256.New) // Noncompliant {{(PasswordBasedKeyDerivationFunction) PBKDF2-SHA256}}
+ _ = key
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRC4TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRC4TestFile.go
new file mode 100644
index 0000000..a495512
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRC4TestFile.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "crypto/rc4"
+)
+
+func main() {
+ key := make([]byte, 16)
+
+ // Create a new RC4 cipher with a 128-bit key
+ cipher, err := rc4.NewCipher(key) // Noncompliant {{(StreamCipher) RC4}}
+ if err != nil {
+ panic(err)
+ }
+
+ // Encrypt data using XOR key stream
+ src := []byte("plaintext")
+ dst := make([]byte, len(src))
+ cipher.XORKeyStream(dst, src)
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptOAEPTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptOAEPTestFile.go
new file mode 100644
index 0000000..94b29d9
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptOAEPTestFile.go
@@ -0,0 +1,24 @@
+package main
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+)
+
+func main() {
+ // Generate a 2048-bit RSA key
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err != nil {
+ panic(err)
+ }
+
+ var pub = &privateKey.PublicKey
+
+ // Encrypt with RSA-OAEP using SHA-256
+ ciphertext, err2 := rsa.EncryptOAEP(sha256.New(), rand.Reader, pub, []byte("hello"), nil) // Noncompliant {{(PublicKeyEncryption) RSA-OAEP}}
+ if err2 != nil {
+ panic(err2)
+ }
+ _ = ciphertext
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptPKCS1v15TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptPKCS1v15TestFile.go
new file mode 100644
index 0000000..14e059b
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRSAEncryptPKCS1v15TestFile.go
@@ -0,0 +1,23 @@
+package main
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+)
+
+func main() {
+ // Generate a 2048-bit RSA key
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err != nil {
+ panic(err)
+ }
+
+ var pub = &privateKey.PublicKey
+
+ // Encrypt with RSA PKCS#1 v1.5
+ ciphertext, err2 := rsa.EncryptPKCS1v15(rand.Reader, pub, []byte("hello")) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err2 != nil {
+ panic(err2)
+ }
+ _ = ciphertext
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRSASignPKCS1v15TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRSASignPKCS1v15TestFile.go
new file mode 100644
index 0000000..6ec1189
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRSASignPKCS1v15TestFile.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+)
+
+func main() {
+ // Generate a 2048-bit RSA key
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err != nil {
+ panic(err)
+ }
+
+ var priv = privateKey
+
+ hashed := []byte("hash of message that is 32 bytes")
+
+ // Sign with RSA PKCS#1 v1.5 using SHA-256
+ sig, err2 := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashed) // Noncompliant {{(Signature) RSA}}
+ if err2 != nil {
+ panic(err2)
+ }
+ _ = sig
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRSASignPSSTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRSASignPSSTestFile.go
new file mode 100644
index 0000000..8c97fa9
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRSASignPSSTestFile.go
@@ -0,0 +1,26 @@
+package main
+
+import (
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+)
+
+func main() {
+ // Generate a 2048-bit RSA key
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err != nil {
+ panic(err)
+ }
+
+ var priv = privateKey
+
+ hashed := []byte("hash of message that is 32 bytes")
+
+ // Sign with RSA-PSS using SHA-256
+ sig, err2 := rsa.SignPSS(rand.Reader, priv, crypto.SHA256, hashed, nil) // Noncompliant {{(Signature) RSA}}
+ if err2 != nil {
+ panic(err2)
+ }
+ _ = sig
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRSATestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRSATestFile.go
new file mode 100644
index 0000000..15c1d63
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRSATestFile.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+)
+
+func main() {
+ // Generate a 2048-bit RSA key
+ privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Noncompliant {{(PublicKeyEncryption) RSA-2048}}
+ if err != nil {
+ panic(err)
+ }
+ _ = privateKey
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoRandTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoRandTestFile.go
new file mode 100644
index 0000000..0556bd7
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoRandTestFile.go
@@ -0,0 +1,15 @@
+package main
+
+import (
+ "crypto/rand"
+ "fmt"
+)
+
+func main() {
+ key := make([]byte, 32)
+ _, err := rand.Read(key) // Noncompliant {{(PseudorandomNumberGenerator) NATIVEPRNG}}
+ if err != nil {
+ panic(err)
+ }
+ fmt.Printf("%x\n", key)
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoSHA1TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoSHA1TestFile.go
new file mode 100644
index 0000000..39a3bc8
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoSHA1TestFile.go
@@ -0,0 +1,17 @@
+package main
+
+import (
+ "crypto/sha1"
+ "fmt"
+)
+
+func main() {
+ h := sha1.New() // Noncompliant {{(MessageDigest) SHA1}}
+ h.Write([]byte("hello"))
+ sum := h.Sum(nil)
+ fmt.Printf("%x\n", sum)
+
+ // Also test sha1.Sum directly
+ checksum := sha1.Sum([]byte("data")) // Noncompliant {{(MessageDigest) SHA1}}
+ fmt.Printf("%x\n", checksum)
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoSHA256TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoSHA256TestFile.go
new file mode 100644
index 0000000..1a4afa3
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoSHA256TestFile.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "crypto/sha256"
+ "fmt"
+)
+
+func main() {
+ // Test sha256.New() - SHA-256
+ h := sha256.New() // Noncompliant {{(MessageDigest) SHA256}}
+ h.Write([]byte("hello"))
+ sum := h.Sum(nil)
+ fmt.Printf("%x\n", sum)
+
+ // Test sha256.New224() - SHA-224
+ h224 := sha256.New224() // Noncompliant {{(MessageDigest) SHA224}}
+ h224.Write([]byte("hello"))
+ sum224 := h224.Sum(nil)
+ fmt.Printf("%x\n", sum224)
+
+ // Test sha256.Sum256() - SHA-256
+ sum256 := sha256.Sum256([]byte("data")) // Noncompliant {{(MessageDigest) SHA256}}
+ _ = sum256
+
+ // Test sha256.Sum224() - SHA-224
+ sum224Direct := sha256.Sum224([]byte("data")) // Noncompliant {{(MessageDigest) SHA224}}
+ _ = sum224Direct
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoSHA3TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoSHA3TestFile.go
new file mode 100644
index 0000000..c564de6
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoSHA3TestFile.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "golang.org/x/crypto/sha3"
+)
+
+func main() {
+ // SHA3-256 hash
+ h256 := sha3.New256() // Noncompliant {{(MessageDigest) SHA3-256}}
+ h256.Write([]byte("test"))
+ _ = h256.Sum(nil)
+
+ // SHA3-512 hash
+ h512 := sha3.New512() // Noncompliant {{(MessageDigest) SHA3-512}}
+ _ = h512
+
+ // Sum256 - direct hash computation
+ hash := sha3.Sum256([]byte("test")) // Noncompliant {{(MessageDigest) SHA3-256}}
+ _ = hash
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoSHA512TestFile.go b/src/test/testdata/go/gocrypto/GoCryptoSHA512TestFile.go
new file mode 100644
index 0000000..9382ed8
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoSHA512TestFile.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "crypto/sha512"
+ "fmt"
+)
+
+func main() {
+ // Test sha512.New() - SHA-512
+ h := sha512.New() // Noncompliant {{(MessageDigest) SHA512}}
+ h.Write([]byte("hello"))
+ sum := h.Sum(nil)
+ fmt.Printf("%x\n", sum)
+
+ // Test sha512.New384() - SHA-384
+ h384 := sha512.New384() // Noncompliant {{(MessageDigest) SHA384}}
+ h384.Write([]byte("hello"))
+ sum384 := h384.Sum(nil)
+ fmt.Printf("%x\n", sum384)
+
+ // Test sha512.Sum512() - SHA-512
+ sum512 := sha512.Sum512([]byte("data")) // Noncompliant {{(MessageDigest) SHA512}}
+ _ = sum512
+
+ // Test sha512.Sum384() - SHA-384
+ sum384Direct := sha512.Sum384([]byte("data")) // Noncompliant {{(MessageDigest) SHA384}}
+ _ = sum384Direct
+}
diff --git a/src/test/testdata/go/gocrypto/GoCryptoTLSTestFile.go b/src/test/testdata/go/gocrypto/GoCryptoTLSTestFile.go
new file mode 100644
index 0000000..2e3f5da
--- /dev/null
+++ b/src/test/testdata/go/gocrypto/GoCryptoTLSTestFile.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "crypto/tls"
+)
+
+func main() {
+ // Dial a TLS connection
+ conf := tls.Config{ // Noncompliant {{(TLS) TLSv1.2}}
+ MinVersion: tls.VersionTLS12,
+ CipherSuites: []uint16{
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ },
+ }
+
+ conn, err := tls.Dial("tcp", "example.com:443", &conf)
+ if err != nil {
+ panic(err)
+ }
+ defer conn.Close()
+}
diff --git a/src/test/testdata/go/gocrypto/a0e0397ec9cc45c48b0f059804ae3969/9073269741158945390/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/a0e0397ec9cc45c48b0f059804ae3969/9073269741158945390/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/a0e0397ec9cc45c48b0f059804ae3969/9073269741158945390/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/b5193bbd4c684df89b31c9c497bab3e1/11711218209443524556/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/b5193bbd4c684df89b31c9c497bab3e1/11711218209443524556/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/b5193bbd4c684df89b31c9c497bab3e1/11711218209443524556/sonar-go-to-slang-darwin-arm64 differ
diff --git a/src/test/testdata/go/gocrypto/f2162b0596bf4497903e3a9e577ec837/2876185731772615516/sonar-go-to-slang-darwin-arm64 b/src/test/testdata/go/gocrypto/f2162b0596bf4497903e3a9e577ec837/2876185731772615516/sonar-go-to-slang-darwin-arm64
new file mode 100755
index 0000000..e3180ee
Binary files /dev/null and b/src/test/testdata/go/gocrypto/f2162b0596bf4497903e3a9e577ec837/2876185731772615516/sonar-go-to-slang-darwin-arm64 differ