diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16d1668 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ + +/kms_signer/bin +/kms_signer/obj +*.exe +/lambda_c2pasign/obj diff --git a/README.md b/README.md new file mode 100644 index 0000000..4f8215d --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ + +# c2pa aws lambda sign demo with aws kms + diff --git a/kms_signer/Program.cs b/kms_signer/Program.cs new file mode 100644 index 0000000..9dcd7d0 --- /dev/null +++ b/kms_signer/Program.cs @@ -0,0 +1,37 @@ +using Amazon.KeyManagementService; + +MemoryStream input = new MemoryStream(); + +try +{ + using (Stream stdin = Console.OpenStandardInput()) + { + byte[] buffer = new byte[2048]; + int bytes; + while ((bytes = stdin.Read(buffer, 0, buffer.Length)) > 0) + { + input.Write(buffer, 0, bytes); + } + } + var client = new AmazonKeyManagementServiceClient(); + + var signResponse = await client.SignAsync(new Amazon.KeyManagementService.Model.SignRequest() + { + KeyId = "", + MessageType = MessageType.RAW, + SigningAlgorithm = SigningAlgorithmSpec.ECDSA_SHA_256, + Message = input + }); + + MemoryStream output = new System.IO.MemoryStream(); + + signResponse.Signature.CopyTo(output); + + output.Position = 0; + + output.CopyTo(Console.OpenStandardOutput()); + + +} +catch (System.Exception e) +{ Console.WriteLine(e.Message); } diff --git a/kms_signer/kms_signer.csproj b/kms_signer/kms_signer.csproj new file mode 100644 index 0000000..1dbc797 --- /dev/null +++ b/kms_signer/kms_signer.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/lambda_c2pasign.sln b/lambda_c2pasign.sln new file mode 100644 index 0000000..de345c0 --- /dev/null +++ b/lambda_c2pasign.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34616.47 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lambda_c2pasign", "lambda_c2pasign\lambda_c2pasign.csproj", "{4756DFF9-F3AD-47DC-9251-C9D72594B232}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "kms_signer", "kms_signer\kms_signer.csproj", "{6945C589-A61A-4758-A0FD-4FA247D26129}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4756DFF9-F3AD-47DC-9251-C9D72594B232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4756DFF9-F3AD-47DC-9251-C9D72594B232}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4756DFF9-F3AD-47DC-9251-C9D72594B232}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4756DFF9-F3AD-47DC-9251-C9D72594B232}.Release|Any CPU.Build.0 = Release|Any CPU + {6945C589-A61A-4758-A0FD-4FA247D26129}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6945C589-A61A-4758-A0FD-4FA247D26129}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6945C589-A61A-4758-A0FD-4FA247D26129}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6945C589-A61A-4758-A0FD-4FA247D26129}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {4101F73E-8132-4AC8-ABB9-79F156DA5D9B} + EndGlobalSection +EndGlobal diff --git a/lambda_c2pasign/Function.cs b/lambda_c2pasign/Function.cs new file mode 100644 index 0000000..1216245 --- /dev/null +++ b/lambda_c2pasign/Function.cs @@ -0,0 +1,147 @@ +using Amazon.Lambda.Core; +using Amazon.Lambda.S3Events; +using Amazon.S3.Model; +using Amazon.S3; +using System.Net; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Converters; +using Amazon.Lambda.Serialization; +using ThirdParty.Json.LitJson; +using Amazon.Runtime.Internal; +using Amazon.Runtime.Internal.Util; +using System.Web; + + + +using Amazon.S3.Util; +using System.Text.Json; +// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class. +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] + +namespace c2panalyze2; + +public class Function +{ + private readonly IAmazonS3 _s3Client; + + public Function() + + { + + _s3Client = new AmazonS3Client(); + + } + + public async Task FunctionHandlerSign(S3Event evnt, ILambdaContext context) + + { + + var s3Event = evnt.Records?.FirstOrDefault(); + + if (s3Event == null) + { + return "No S3 event detected."; + } + + string s3BucketPathSigned = "data_sign"; + + try + { + s3BucketPathSigned = Environment.GetEnvironmentVariable("s3BucketPathSigned").TrimStart('/'); + } + catch + { + } + + string s3BucketPath = "data"; + + try + { + s3BucketPath = Environment.GetEnvironmentVariable("s3BucketPath").TrimStart('/'); + } + catch + { + } + + + + string bucketName = s3Event.S3.Bucket.Name; + + string fileName = s3Event.S3.Object.Key; + + Console.WriteLine("s3BucketPath " + s3BucketPath); + Console.WriteLine("s3BucketPathSigned " + s3BucketPathSigned); + Console.WriteLine("bucketName " + bucketName); + Console.WriteLine("fileName " + fileName); + + string extension = System.IO.Path.GetExtension(fileName); + + string _outputDirectory = "/tmp/" + fileName.Replace(extension, ""); + + string _tmpFilename = "/tmp/" + fileName; + + string _tmpFilenameSigned = "/tmp/" + fileName.Replace(extension, "") + "_signed" + extension; + + Console.WriteLine("_tmpFilename " + _tmpFilename); + + Console.WriteLine("_tmpFilenameSigned " + _tmpFilenameSigned); + + Console.WriteLine("_outputDirectory " + _outputDirectory); + + + try + + { + + Console.WriteLine("get file"); + var getRequest = new GetObjectRequest + + { + BucketName = bucketName, + Key = fileName + + }; + var response = _s3Client.GetObjectAsync(getRequest).GetAwaiter().GetResult(); + response.WriteResponseStreamToFileAsync(_tmpFilename, false, new CancellationTokenSource().Token).GetAwaiter().GetResult(); + + } + catch (Exception e) + { + Console.WriteLine("get File failed " + e.Message + "@" + e.StackTrace); + } + + + try + { + + processC2PA run3 = new processC2PA(_tmpFilename, _outputDirectory); + + string result3 = run3.runSign(_tmpFilenameSigned); + + Console.WriteLine("runSign Result " + result3); + + s3Load s3Loader1 = new s3Load("", "", "eu-central-1"); + + List _ingredientFiles1 = new List(); + _ingredientFiles1.Add(_tmpFilenameSigned); + + Console.WriteLine("Upload file Sign " + _tmpFilenameSigned); + + string s3result1 = s3Loader1.putS3Files(_ingredientFiles1, bucketName, s3BucketPathSigned).GetAwaiter().GetResult(); + + Console.WriteLine("putS3Files Result " + s3result1); + + File.Delete(_tmpFilenameSigned); + File.Delete(_tmpFilename); + } + catch (Exception e) + { + Console.WriteLine("RunSign or Upload failed Error " + e.Message + "@" + e.StackTrace); + } + + + return "ok"; + } + + +} \ No newline at end of file diff --git a/lambda_c2pasign/Properties/launchSettings.json b/lambda_c2pasign/Properties/launchSettings.json new file mode 100644 index 0000000..c1fabf8 --- /dev/null +++ b/lambda_c2pasign/Properties/launchSettings.json @@ -0,0 +1,10 @@ +{ + "profiles": { + "Mock Lambda Test Tool": { + "commandName": "Executable", + "commandLineArgs": "--port 5050", + "workingDirectory": ".\\bin\\$(Configuration)\\net8.0", + "executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-8.0.exe" + } + } +} \ No newline at end of file diff --git a/lambda_c2pasign/c2pa/AWSSDK.Core.dll b/lambda_c2pasign/c2pa/AWSSDK.Core.dll new file mode 100644 index 0000000..831d930 Binary files /dev/null and b/lambda_c2pasign/c2pa/AWSSDK.Core.dll differ diff --git a/lambda_c2pasign/c2pa/AWSSDK.KeyManagementService.dll b/lambda_c2pasign/c2pa/AWSSDK.KeyManagementService.dll new file mode 100644 index 0000000..d6db701 Binary files /dev/null and b/lambda_c2pasign/c2pa/AWSSDK.KeyManagementService.dll differ diff --git a/lambda_c2pasign/c2pa/c2patool b/lambda_c2pasign/c2pa/c2patool new file mode 100644 index 0000000..9201401 Binary files /dev/null and b/lambda_c2pasign/c2pa/c2patool differ diff --git a/lambda_c2pasign/c2pa/kms_signer b/lambda_c2pasign/c2pa/kms_signer new file mode 100644 index 0000000..6699a94 Binary files /dev/null and b/lambda_c2pasign/c2pa/kms_signer differ diff --git a/lambda_c2pasign/c2pa/kms_signer.deps.json b/lambda_c2pasign/c2pa/kms_signer.deps.json new file mode 100644 index 0000000..5ca4bfa --- /dev/null +++ b/lambda_c2pasign/c2pa/kms_signer.deps.json @@ -0,0 +1,59 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v8.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v8.0": { + "kms_signer/1.0.0": { + "dependencies": { + "AWSSDK.KeyManagementService": "3.7.400.53" + }, + "runtime": { + "kms_signer.dll": {} + } + }, + "AWSSDK.Core/3.7.400.53": { + "runtime": { + "lib/net8.0/AWSSDK.Core.dll": { + "assemblyVersion": "3.3.0.0", + "fileVersion": "3.7.400.53" + } + } + }, + "AWSSDK.KeyManagementService/3.7.400.53": { + "dependencies": { + "AWSSDK.Core": "3.7.400.53" + }, + "runtime": { + "lib/net8.0/AWSSDK.KeyManagementService.dll": { + "assemblyVersion": "3.3.0.0", + "fileVersion": "3.7.400.53" + } + } + } + } + }, + "libraries": { + "kms_signer/1.0.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "AWSSDK.Core/3.7.400.53": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OwJTHfD3tXKLPiB/UUr6SSigFycQm6JNTReh5j2kYJP0CgcZmV+qeePEpIptxCVbq28esef/8hdzezkzNhN+fA==", + "path": "awssdk.core/3.7.400.53", + "hashPath": "awssdk.core.3.7.400.53.nupkg.sha512" + }, + "AWSSDK.KeyManagementService/3.7.400.53": { + "type": "package", + "serviceable": true, + "sha512": "sha512-RyBv5ZgUAzvLkF685BIx/ey+0KNY7IrFNImQdggqYVm0zyS0nOLu+2sV7Kg3bF6QT7X1tybVNKYhnz07ET5DVQ==", + "path": "awssdk.keymanagementservice/3.7.400.53", + "hashPath": "awssdk.keymanagementservice.3.7.400.53.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/lambda_c2pasign/c2pa/kms_signer.dll b/lambda_c2pasign/c2pa/kms_signer.dll new file mode 100644 index 0000000..cf65e57 Binary files /dev/null and b/lambda_c2pasign/c2pa/kms_signer.dll differ diff --git a/lambda_c2pasign/c2pa/kms_signer.pdb b/lambda_c2pasign/c2pa/kms_signer.pdb new file mode 100644 index 0000000..ab9e008 Binary files /dev/null and b/lambda_c2pasign/c2pa/kms_signer.pdb differ diff --git a/lambda_c2pasign/c2pa/kms_signer.runtimeconfig.json b/lambda_c2pasign/c2pa/kms_signer.runtimeconfig.json new file mode 100644 index 0000000..becfaea --- /dev/null +++ b/lambda_c2pasign/c2pa/kms_signer.runtimeconfig.json @@ -0,0 +1,12 @@ +{ + "runtimeOptions": { + "tfm": "net8.0", + "framework": { + "name": "Microsoft.NETCore.App", + "version": "8.0.0" + }, + "configProperties": { + "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false + } + } +} \ No newline at end of file diff --git a/lambda_c2pasign/certs/es256_certs.pem b/lambda_c2pasign/certs/es256_certs.pem new file mode 100644 index 0000000..0cc17d2 --- /dev/null +++ b/lambda_c2pasign/certs/es256_certs.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIChzCCAi6gAwIBAgIUcCTmJHYF8dZfG0d1UdT6/LXtkeYwCgYIKoZIzj0EAwIw +gYwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJU29tZXdoZXJl +MScwJQYDVQQKDB5DMlBBIFRlc3QgSW50ZXJtZWRpYXRlIFJvb3QgQ0ExGTAXBgNV +BAsMEEZPUiBURVNUSU5HX09OTFkxGDAWBgNVBAMMD0ludGVybWVkaWF0ZSBDQTAe +Fw0yMjA2MTAxODQ2NDBaFw0zMDA4MjYxODQ2NDBaMIGAMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExEjAQBgNVBAcMCVNvbWV3aGVyZTEfMB0GA1UECgwWQzJQQSBU +ZXN0IFNpZ25pbmcgQ2VydDEZMBcGA1UECwwQRk9SIFRFU1RJTkdfT05MWTEUMBIG +A1UEAwwLQzJQQSBTaWduZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQPaL6R +kAkYkKU4+IryBSYxJM3h77sFiMrbvbI8fG7w2Bbl9otNG/cch3DAw5rGAPV7NWky +l3QGuV/wt0MrAPDoo3gwdjAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG +AQUFBwMEMA4GA1UdDwEB/wQEAwIGwDAdBgNVHQ4EFgQUFznP0y83joiNOCedQkxT +tAMyNcowHwYDVR0jBBgwFoAUDnyNcma/osnlAJTvtW6A4rYOL2swCgYIKoZIzj0E +AwIDRwAwRAIgOY/2szXjslg/MyJFZ2y7OH8giPYTsvS7UPRP9GI9NgICIDQPMKrE +LQUJEtipZ0TqvI/4mieoyRCeIiQtyuS0LACz +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICajCCAg+gAwIBAgIUfXDXHH+6GtA2QEBX2IvJ2YnGMnUwCgYIKoZIzj0EAwIw +dzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRIwEAYDVQQHDAlTb21ld2hlcmUx +GjAYBgNVBAoMEUMyUEEgVGVzdCBSb290IENBMRkwFwYDVQQLDBBGT1IgVEVTVElO +R19PTkxZMRAwDgYDVQQDDAdSb290IENBMB4XDTIyMDYxMDE4NDY0MFoXDTMwMDgy +NzE4NDY0MFowgYwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTESMBAGA1UEBwwJ +U29tZXdoZXJlMScwJQYDVQQKDB5DMlBBIFRlc3QgSW50ZXJtZWRpYXRlIFJvb3Qg +Q0ExGTAXBgNVBAsMEEZPUiBURVNUSU5HX09OTFkxGDAWBgNVBAMMD0ludGVybWVk +aWF0ZSBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHllI4O7a0EkpTYAWfPM +D6Rnfk9iqhEmCQKMOR6J47Rvh2GGjUw4CS+aLT89ySukPTnzGsMQ4jK9d3V4Aq4Q +LsOjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBQOfI1yZr+iyeUAlO+1boDitg4vazAfBgNVHSMEGDAWgBRembiG4Xgb2VcVWnUA +UrYpDsuojDAKBggqhkjOPQQDAgNJADBGAiEAtdZ3+05CzFo90fWeZ4woeJcNQC4B +84Ill3YeZVvR8ZECIQDVRdha1xEDKuNTAManY0zthSosfXcvLnZui1A/y/DYeg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/lambda_c2pasign/certs/manifest.json b/lambda_c2pasign/certs/manifest.json new file mode 100644 index 0000000..609cb9f --- /dev/null +++ b/lambda_c2pasign/certs/manifest.json @@ -0,0 +1,72 @@ +{ + "alg": "es256", + "sign_cert": "es256_certs.pem", + "ta_url": "http://timestamp.digicert.com", + "claim_generator_info": [ + { + "name": "Demo-Signer", + "version": "1.0" + } + ], + "assertions": [ + { + "label": "c2pa.actions", + "data": { + "actions": [ + { + "action": "c2pa.opened" + }, + { + "action": "c2pa.color_adjustments", + "parameters": { + "name": "brightnesscontrast" + } + }, + { + "action": "c2pa.placed" + } + ] + } + }, + { + "label": "de.wdr.custom", + "data": { + "organization": "Westdeutscher Rundfunk ", + "platform": "My Platform", + "news": [ + { + "info": " Comment, claims...", + "person": "Journalist", + "time": "Time", + "location": "Location" + } + ] + } + }, + { + "label": "stds.schema-org.ClaimReview", + "data": { + "@context": "http://schema.org", + "@type": "ClaimReview", + "author": { + "@type": "Organization", + "name": "WDR" + }, + "claimReviewed": "Claim review", + "datePublished": "Here Date", + "itemReviewed": { + "@type": "ImageObject", + "caption": "What video" + }, + "reviewBody": "My review", + "reviewRating": { + "@type": "Rating", + "alternateName": "Verified", + "bestRating": "5", + "ratingValue": "5", + "worstRating": "1" + } + } + } + ] +} \ No newline at end of file diff --git a/lambda_c2pasign/lambda_c2pasign.csproj b/lambda_c2pasign/lambda_c2pasign.csproj new file mode 100644 index 0000000..1268b8f --- /dev/null +++ b/lambda_c2pasign/lambda_c2pasign.csproj @@ -0,0 +1,53 @@ + + + net8.0 + enable + enable + true + Lambda + + true + + true + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + Always + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + \ No newline at end of file diff --git a/lambda_c2pasign/runC2PA.cs b/lambda_c2pasign/runC2PA.cs new file mode 100644 index 0000000..0e768bb --- /dev/null +++ b/lambda_c2pasign/runC2PA.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Security.Cryptography.X509Certificates; +using System.Text.Json; +using System.Globalization; +using System.Numerics; + +namespace c2panalyze2 +{ + public class certchainelement + { + public string issuer { get; set; } + public DateTime notAfter { get; set; } + public DateTime notBefore { get; set; } + public string cert_serial_number { get; set; } + public string subject { get; set; } + public string signatureAlgorithm { get; set; } + public string thumbPrint { get; set; } + public int version { get; set; } + } + + public class processC2PA + { + + string _filetoAnalyze = ""; + + string _outputFolder = ""; + + string _outputFile = ""; + + + + public processC2PA(string filetoAnalyze, string outputFolder) + { + _filetoAnalyze = filetoAnalyze; + _outputFolder = outputFolder; + } + + + public string runAssertions() + { + if (_filetoAnalyze != "") + { + Process c2parunner1 = new Process(); + + c2parunner1.StartInfo.FileName = Path.Combine(Directory.GetCurrentDirectory(), "c2pa", "c2patool"); + //c2parunner3.StartInfo.Arguments = _filetoAnalyze + " -d"; + c2parunner1.StartInfo.Arguments = _filetoAnalyze + " --output " + _outputFolder; + Console.WriteLine("runC2PA 1 " + c2parunner1.StartInfo.Arguments); + c2parunner1.StartInfo.CreateNoWindow = true; + c2parunner1.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory(); + c2parunner1.StartInfo.UseShellExecute = false; + c2parunner1.StartInfo.RedirectStandardError = true; + c2parunner1.StartInfo.RedirectStandardOutput = true; + c2parunner1.Start(); + + if (!c2parunner1.WaitForExit(20 * 1000)) + { + try + { + Console.WriteLine("runC2PA: 'msg': 'c2patool process timed out'"); + c2parunner1.Kill(); + + } + catch { } + } + + string s_runc2pa_out1 = ""; + string s_runc2pa_err1 = ""; + + try + { + s_runc2pa_out1 = c2parunner1.StandardOutput.ReadToEnd().Trim(); + s_runc2pa_err1 = c2parunner1.StandardError.ReadToEnd().Trim(); + c2parunner1.WaitForExit(); + } + catch + { } + + Console.WriteLine("runC2PA 1: 'msg': 'c2patool process finished'"); + + Console.WriteLine("runC2PA 1: 'msg': 'c2patool process s_runc2pa_out'" + s_runc2pa_out1); + + Console.WriteLine("runC2PA 1: 'msg': 'c2patool process s_runc2pa_err'" + s_runc2pa_out1); + + return s_runc2pa_out1; + } + else + { + return ""; + } + } + + public string runCerts() + { + if (_filetoAnalyze != "") + { + try + { + Process c2parunner2 = new Process(); + + string s_runc2pa_out2 = ""; + string s_runc2pa_err2 = ""; + + c2parunner2.StartInfo.FileName = Path.Combine(Directory.GetCurrentDirectory(), "c2pa", "c2patool"); + //c2parunner3.StartInfo.Arguments = _filetoAnalyze + " -d"; + c2parunner2.StartInfo.Arguments = _filetoAnalyze + " --certs"; + Console.WriteLine("runC2PA 2 " + c2parunner2.StartInfo.Arguments); + c2parunner2.StartInfo.CreateNoWindow = true; + c2parunner2.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory(); + c2parunner2.StartInfo.UseShellExecute = false; + c2parunner2.StartInfo.RedirectStandardError = true; + c2parunner2.StartInfo.RedirectStandardOutput = true; + c2parunner2.Start(); + + if (!c2parunner2.WaitForExit(20 * 1000)) + { + try + { + Console.WriteLine("runC2PA 2: 'msg': 'c2patool process timed out'"); + c2parunner2.Kill(); + + } + catch { } + } + + try + { + s_runc2pa_out2 = c2parunner2.StandardOutput.ReadToEnd().Trim(); + s_runc2pa_err2 = c2parunner2.StandardError.ReadToEnd().Trim(); + c2parunner2.WaitForExit(); + } + catch + { } + + string[] certs = s_runc2pa_out2.Split("-----END CERTIFICATE-----"); + + Console.WriteLine("runC2PA 2: 's_runc2pa_out2': " + s_runc2pa_out2); + + List certchain = new List(); + + foreach (string currcert in certs) + { + if (currcert.Contains("-----BEGIN CERTIFICATE-----")) + { + + Console.WriteLine("runC2PA 2: 'currcert': " + currcert + "-----END CERTIFICATE-----\r\n"); + byte[] bytes = Encoding.ASCII.GetBytes(currcert + "-----END CERTIFICATE-----\r\n"); + try + { + certchainelement currchainelement = new certchainelement(); + var cert = new X509Certificate2(bytes); + currchainelement.issuer = cert.Issuer; + currchainelement.cert_serial_number = BigInteger.Parse(cert.SerialNumber, NumberStyles.HexNumber).ToString(); + //currchainelement.cert_serial_number = cert.SerialNumber; + currchainelement.subject = cert.Subject; + currchainelement.thumbPrint = cert.Thumbprint; + currchainelement.notBefore = cert.NotBefore; + currchainelement.notAfter = cert.NotAfter; + currchainelement.signatureAlgorithm = cert.SignatureAlgorithm.FriendlyName.ToString(); + currchainelement.version = cert.Version; + certchain.Add(currchainelement); + } + catch (System.Exception e) + { + Console.WriteLine("runC2PA: 'runCerts interim ': " + e.StackTrace + " @ " + e.Message); + } + + + } + } + string jsonString = JsonSerializer.Serialize(certchain); + + File.WriteAllText(Path.Combine(_outputFolder, "certchain.json"), jsonString); + + Console.WriteLine("runC2PA 2: 'msg': 'c2patool process finished'"); + + Console.WriteLine("runC2PA 2: 'msg': 'c2patool process s_runc2pa_out'" + s_runc2pa_out2); + + Console.WriteLine("runC2PA 2: 'msg': 'c2patool process s_runc2pa_err'" + s_runc2pa_out2); + + return s_runc2pa_out2; + } + catch(System.Exception e) + { + Console.WriteLine("runC2PA: 'runCerts': " + e.StackTrace + " @ " + e.Message); + return ""; + } + + } + else + { + return ""; + } + } + + public string runSign(string outputFile) + { + if (_filetoAnalyze != "") + { + Process c2parunner3 = new Process(); + + c2parunner3.StartInfo.FileName = Path.Combine(Directory.GetCurrentDirectory(), "c2pa", "c2patool"); + c2parunner3.StartInfo.Arguments = _filetoAnalyze + " -m " + Path.Combine(Directory.GetCurrentDirectory(), "certs","manifest.json") + " --signer-path " + Path.Combine(Directory.GetCurrentDirectory(), "c2pa", "kms_signer") + " -o " + outputFile; + + Console.WriteLine("runC2PA 3 " + c2parunner3.StartInfo.Arguments); + + c2parunner3.StartInfo.CreateNoWindow = true; + c2parunner3.StartInfo.WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "c2pa"); + c2parunner3.StartInfo.UseShellExecute = false; + c2parunner3.StartInfo.RedirectStandardError = true; + c2parunner3.StartInfo.RedirectStandardOutput = true; + c2parunner3.Start(); + + if (!c2parunner3.WaitForExit(60 * 1000)) + { + try + { + Console.WriteLine("runC2PA 3: 'msg': 'c2patool process timed out'"); + c2parunner3.Kill(); + + } + catch { } + } + + string s_runc2pa_out1 = ""; + string s_runc2pa_err1 = ""; + + try + { + s_runc2pa_out1 = c2parunner3.StandardOutput.ReadToEnd().Trim(); + s_runc2pa_err1 = c2parunner3.StandardError.ReadToEnd().Trim(); + c2parunner3.WaitForExit(); + } + catch + { } + + Console.WriteLine("runC2PA 3: 'msg': 'c2patool process finished s_runc2pa_out1'" + s_runc2pa_out1); + + Console.WriteLine("runC2PA 3: 'msg': 'c2patool process finished s_runc2pa_err1'" + s_runc2pa_err1); + + try + { + FileInfo fi = new FileInfo(outputFile); + + Console.WriteLine("runC2PA 3: 'msg': 'c2patool process size '" + fi.Length.ToString()); + } + catch { } + return s_runc2pa_out1; + } + else + { + return ""; + } + } + } +} diff --git a/lambda_c2pasign/s3Load.cs b/lambda_c2pasign/s3Load.cs new file mode 100644 index 0000000..b7c9666 --- /dev/null +++ b/lambda_c2pasign/s3Load.cs @@ -0,0 +1,290 @@ +using Amazon; +using Amazon.Runtime; +using Amazon.S3; +using Amazon.S3.Transfer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace c2panalyze2 +{ + public class s3Load + { + + private static string aws_access_key = ""; + + private static string aws_secret = ""; + + private static RegionEndpoint aws_region; + + private static IAmazonS3 client; + + private static string errormessage = ""; + + public s3Load(string _aws_access_key, string _aws_secret, string _aws_region) + { + errormessage = ""; + aws_access_key = _aws_access_key; + if ((_aws_secret != "") && (_aws_secret != null)) + { + try + { + aws_secret = ASCIIEncoding.ASCII.GetString(Convert.FromBase64String(_aws_secret)); + } + catch + { } + } + else + { + aws_secret = ""; + } + + aws_region = returnS3Region(_aws_region); + + } + + public async Task putS3Files(List FilesToUploadFinal, string bucket, string s3BucketPath) + { + string returnerrors = ""; + try + { + + + + var allTasks = new List(); + + int maxconctasks = 2; + try + { + maxconctasks = Environment.ProcessorCount / 2; + + if (maxconctasks < 1) + { + maxconctasks = 1; + } + } + catch + { } + + + try + { + AmazonS3Client s3client; + ////DOWNLOAD TRANSFERUTILITY + if ((aws_access_key == "")) + { + s3client = new AmazonS3Client( + new AmazonS3Config + { + Timeout = TimeSpan.FromSeconds(100), // Default value is 100 seconds + //ReadWriteTimeout = TimeSpan.FromSeconds(300), // Default value is 300 seconds + MaxErrorRetry = 4, // Default value is 4 retries + RegionEndpoint = aws_region + }); + } + else + { + s3client = new AmazonS3Client(aws_access_key, aws_secret, + new AmazonS3Config + { + Timeout = TimeSpan.FromSeconds(100), // Default value is 100 seconds + //ReadWriteTimeout = TimeSpan.FromSeconds(300), // Default value is 300 seconds + MaxErrorRetry = 4, // Default value is 4 retries + RegionEndpoint = aws_region + }); + } + + TransferUtilityConfig transferUtilityConfig = new TransferUtilityConfig(); + if (FilesToUploadFinal.Count > 100) + { + transferUtilityConfig.ConcurrentServiceRequests = 100; + } + else if (FilesToUploadFinal.Count > 50) + { + transferUtilityConfig.ConcurrentServiceRequests = 50; + } + else + { + transferUtilityConfig.ConcurrentServiceRequests = 10; + } + + + TransferUtility fileTransferUtility = new TransferUtility(s3client, transferUtilityConfig); + + var throttler = new SemaphoreSlim(initialCount: maxconctasks); + foreach (string currfile in FilesToUploadFinal) + { + throttler.Wait(); + allTasks.Add( + Task.Run(async () => + { + try + { + var uploadRequest = + new TransferUtilityUploadRequest + { + BucketName = bucket, + //FIXME name data and data_signed need to be parametrized !!! + + Key = Path.Combine(s3BucketPath.TrimStart('/'), currfile.Replace("\\", "/").Replace("/tmp/data/", "").Replace("/tmp/data_sign/", "")), + FilePath = currfile + }; + + Console.WriteLine("DEBUG Key upload " + Path.Combine(s3BucketPath.TrimStart('/'), currfile.Replace("\\", "/").Replace("/tmp/data/", "").Replace("/tmp/data_sign/", ""))); + await fileTransferUtility.UploadAsync(uploadRequest); + + + throttler.Release(); + } + catch (System.Exception e) + { + errormessage = "gets3files3 AWS S3 error2 occurred.Exception: " + e.Message; + throttler.Release(); + + } + finally + { + throttler.Release(); + } + })); + } + Task.WhenAll(allTasks).Wait(); + + + fileTransferUtility.Dispose(); + s3client.Dispose(); + } + catch (AmazonS3Exception amazonS3Exception) + { + errormessage = "gets3files3 AWS S3 error occurred.Exception: " + amazonS3Exception.ToString(); + return errormessage; + } + catch (Exception e) + { + errormessage = "gets3files3 generic S3 error occurred.Exception: " + e.Message; + return errormessage; + } + } + catch (System.Exception e) + { + returnerrors = e.Message; + } + + return returnerrors; + + } + + public static Amazon.RegionEndpoint returnS3Region(string _region) + { + Amazon.RegionEndpoint AWSEndpoint; + + switch (_region) + { + case "eucentral1": + AWSEndpoint = Amazon.RegionEndpoint.EUCentral1; + break; + case "eu-central-1": + AWSEndpoint = Amazon.RegionEndpoint.EUCentral1; + break; + case "euwest1": + AWSEndpoint = Amazon.RegionEndpoint.EUWest1; + break; + case "eu-west-1": + AWSEndpoint = Amazon.RegionEndpoint.EUWest1; + break; + case "euwest2": + AWSEndpoint = Amazon.RegionEndpoint.EUWest2; + break; + case "eu-west-2": + AWSEndpoint = Amazon.RegionEndpoint.EUWest2; + break; + case "euwest3": + AWSEndpoint = Amazon.RegionEndpoint.EUWest3; + break; + case "eu-west-3": + AWSEndpoint = Amazon.RegionEndpoint.EUWest3; + break; + case "eunorth1": + AWSEndpoint = Amazon.RegionEndpoint.EUNorth1; + break; + case "eu-north-1": + AWSEndpoint = Amazon.RegionEndpoint.EUNorth1; + break; + case "useast1": + AWSEndpoint = Amazon.RegionEndpoint.USEast1; + break; + case "us-east-1": + AWSEndpoint = Amazon.RegionEndpoint.USEast1; + break; + case "useast2": + AWSEndpoint = Amazon.RegionEndpoint.USEast2; + break; + case "us-east-2": + AWSEndpoint = Amazon.RegionEndpoint.USEast2; + break; + case "uswest1": + AWSEndpoint = Amazon.RegionEndpoint.USWest1; + break; + case "us-west-1": + AWSEndpoint = Amazon.RegionEndpoint.USWest1; + break; + case "uswest2": + AWSEndpoint = Amazon.RegionEndpoint.USWest2; + break; + case "us-west-2": + AWSEndpoint = Amazon.RegionEndpoint.USWest2; + break; + case "apnortheast1": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast1; + break; + case "ap-northeast-1": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast1; + break; + case "apnortheast2": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast2; + break; + case "ap-northeast-2": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast2; + break; + case "apnortheast3": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast3; + break; + case "ap-northeast-3": + AWSEndpoint = Amazon.RegionEndpoint.APNortheast3; + break; + case "apsouth1": + AWSEndpoint = Amazon.RegionEndpoint.APSouth1; + break; + case "ap-south-1": + AWSEndpoint = Amazon.RegionEndpoint.APSouth1; + break; + case "apsoutheast1": + AWSEndpoint = Amazon.RegionEndpoint.APSoutheast1; + break; + case "ap-southeast-1": + AWSEndpoint = Amazon.RegionEndpoint.APSoutheast1; + break; + case "apsoutheast2": + AWSEndpoint = Amazon.RegionEndpoint.APSoutheast2; + break; + case "ap-southeast-2": + AWSEndpoint = Amazon.RegionEndpoint.APSoutheast2; + break; + case "apcacentral1": + AWSEndpoint = Amazon.RegionEndpoint.CACentral1; + break; + case "ap-cacentral-1": + AWSEndpoint = Amazon.RegionEndpoint.CACentral1; + break; + default: + AWSEndpoint = Amazon.RegionEndpoint.EUWest1; + break; + } + return AWSEndpoint; + } + } + + +}