-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from Daniel15/gpg
Add support for GPG
- Loading branch information
Showing
30 changed files
with
1,081 additions
and
182 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -312,3 +312,5 @@ __pycache__/ | |
|
||
# OpenCover UI analysis results | ||
OpenCover/ | ||
.gnupg/ | ||
secrets/ |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!-- Workaround for https://github.com/dotnet/cli/issues/7532 --> | ||
<Project> | ||
<PropertyGroup | ||
Condition="'$(OS)' == 'Windows_NT' and | ||
'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and | ||
'$(SelfContained)' != 'true'" | ||
> | ||
<RunCommand Condition="'$(PlatformTarget)' == 'x86'">$(MSBuildProgramFiles32)\dotnet\dotnet</RunCommand> | ||
<RunCommand Condition="'$(PlatformTarget)' == 'x64'">$(ProgramW6432)\dotnet\dotnet</RunCommand> | ||
</PropertyGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Copyright (c) 2019 Daniel Lo Nigro (Daniel15) | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
using System.Security; | ||
|
||
namespace SecureSign.Core.Extensions | ||
{ | ||
public static class SecureStringExtensions | ||
{ | ||
public static string ToAnsiString(this SecureString value) | ||
{ | ||
var valuePtr = IntPtr.Zero; | ||
try | ||
{ | ||
valuePtr = Marshal.SecureStringToGlobalAllocAnsi(value); | ||
return Marshal.PtrToStringAnsi(valuePtr); | ||
} | ||
finally | ||
{ | ||
Marshal.ZeroFreeGlobalAllocAnsi(valuePtr); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Copyright (c) 2019 Daniel Lo Nigro (Daniel15) | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
namespace SecureSign.Core | ||
{ | ||
/// <summary> | ||
/// Represents a type of signing key supported by SecureSign | ||
/// </summary> | ||
public enum KeyType | ||
{ | ||
/// <summary> | ||
/// Authenticode (eg. to sign Windows installers) | ||
/// </summary> | ||
Authenticode, | ||
|
||
/// <summary> | ||
/// GnuPG | ||
/// </summary> | ||
Gpg, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* Copyright (c) 2019 Daniel Lo Nigro (Daniel15) | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
using System; | ||
using System.IO; | ||
|
||
namespace SecureSign.Core | ||
{ | ||
public static class KeyTypeUtils | ||
{ | ||
/// <summary> | ||
/// Gets the <see cref="KeyType"/> that this file could contain. | ||
/// </summary> | ||
/// <param name="filename">Name of the file</param> | ||
/// <returns>The key type</returns> | ||
public static KeyType FromFilename(string filename) | ||
{ | ||
switch (Path.GetExtension(filename)) | ||
{ | ||
case ".pfx": | ||
return KeyType.Authenticode; | ||
case ".gpg": | ||
return KeyType.Gpg; | ||
default: | ||
throw new Exception("Unsupported key type"); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/** | ||
* Copyright (c) 2019 Daniel Lo Nigro (Daniel15) | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
using System; | ||
using System.IO; | ||
using Libgpgme; | ||
using Microsoft.Extensions.Options; | ||
using SecureSign.Core.Models; | ||
|
||
namespace SecureSign.Core.Signers | ||
{ | ||
/// <summary> | ||
/// Handles signing artifacts using GPG. | ||
/// </summary> | ||
public class GpgSigner : IGpgSigner | ||
{ | ||
private readonly Context _ctx; | ||
private readonly PathConfig _pathConfig; | ||
private static readonly object _signLock = new object(); | ||
|
||
public GpgSigner(IOptions<PathConfig> pathConfig, Context ctx) | ||
{ | ||
_ctx = ctx; | ||
_pathConfig = pathConfig.Value; | ||
} | ||
|
||
/// <summary> | ||
/// Signs the specified artifact using GPG | ||
/// </summary> | ||
/// <param name="input">Bytes to sign</param> | ||
/// <param name="keygrip">Hex representation of keygrip</param> | ||
/// <param name="secretKeyFile">Contents of the secret key file</param> | ||
/// <param name="fingerprint">Fingerprint of the key</param> | ||
/// <returns>ASCII-armored signature</returns> | ||
public byte[] Sign(byte[] input, string keygrip, byte[] secretKeyFile, string fingerprint) | ||
{ | ||
// Since this signer messes with some global state (private keys in the GPG home directory), | ||
// we must lock to ensure no other signing requests happen concurrently. | ||
lock (_signLock) | ||
{ | ||
var keygripPath = Path.Combine(_pathConfig.GpgHome, "private-keys-v1.d", keygrip + ".key"); | ||
var inputPath = Path.GetTempFileName(); | ||
try | ||
{ | ||
File.WriteAllBytes(keygripPath, secretKeyFile); | ||
File.WriteAllBytes(inputPath, input); | ||
|
||
var key = _ctx.KeyStore.GetKey(fingerprint, secretOnly: true); | ||
_ctx.Signers.Clear(); | ||
_ctx.Signers.Add(key); | ||
_ctx.Armor = true; | ||
|
||
using (var inputData = new GpgmeFileData(inputPath, FileMode.Open, FileAccess.Read)) | ||
using (var sigData = new GpgmeMemoryData { FileName = "signature.asc" }) | ||
{ | ||
var result = _ctx.Sign(inputData, sigData, SignatureMode.Detach); | ||
if (result.InvalidSigners != null) | ||
{ | ||
throw new Exception($"Could not sign: {result.InvalidSigners.Reason}"); | ||
} | ||
|
||
using (var memStream = new MemoryStream()) | ||
{ | ||
sigData.Seek(0, SeekOrigin.Begin); | ||
sigData.CopyTo(memStream); | ||
return memStream.GetBuffer(); | ||
} | ||
} | ||
} | ||
finally | ||
{ | ||
File.Delete(keygripPath); | ||
File.Delete(inputPath); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.