Tuesday, 27 October 2009

C# GPG Implementation

public class GPG
{
private ILog log = LogManager.GetLogger(MethodInfo.GetCurrentMethod().DeclaringType);

private const string DEFAULT_GPG_PATH = @"C:\Program Files\GNU\GnuPG\";

private const string DECRYPT_ARGS = @"
--batch --output ""{0}"" --decrypt ""{1}""";
private const string ENCRYPT_ARGS = @"
--batch --output ""{0}"" --encrypt --recipient ""{2}"" ""{1}""";

private string _gpgPath;

public GPG()
{
_gpgPath = DEFAULT_GPG_PATH;
}

public string GpgPath
{
set { _gpgPath = value; }
}

public string DecryptFile(string filePath)
{
string outFile;
if (filePath.EndsWith("
.gpg"))
{
outFile = filePath.Remove(filePath.Length - 4, 4);
}else
{
outFile = string.Format("
{0}{1}", filePath, ".out");
}
return DecryptFile(filePath,outFile);
}

public string DecryptFile(string filePath, string outFile)
{
string args = string.Format(DECRYPT_ARGS, outFile, filePath);
ExecuteGPG(args);
return outFile;
}

public string EncryptFile(string filePath, string userId)
{
string outFile = string.Format("
{0}{1}", filePath, ".gpg");
return EncryptFile(filePath, outFile, userId);
}

public string EncryptFile(string filePath, string outFile, string userId)
{
string args = string.Format(ENCRYPT_ARGS, outFile, filePath, userId);
ExecuteGPG(args);
return outFile;
}

private void ExecuteGPG(string args)
{
try
{
Process process = new Process();
string programPath = string.Format(@"
""{0}""", Path.Combine(_gpgPath, "gpg.exe"));

if(!File.Exists(programPath))
{
string error = string.Format("
Invalid gpg.exe path: {0}, please set GpgPath property", programPath);
log.Error(error);
throw new Exception(error);
}

log.InfoFormat("
Executing: {0} {1}", programPath, args);

process.StartInfo.FileName = programPath;
//Open as readonly
process.StartInfo.Arguments = args;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.WorkingDirectory = _gpgPath;

process.Start();

StreamReader reader = process.StandardOutput;
string output = reader.ReadToEnd();

log.InfoFormat("
Output: {0}", output);
}
catch (Exception ex)
{
log.Error("
Failed to execute gpg.exe command",ex);
throw;
}
}
}

PGP/GPG Encryption

Public/Private keys are used to send encrypted data between clients. The receiving client generates public/private key pair and sends the public key to all contributing clients. The contributing clients are using public key to decrypt the file. Receiving client is using the private key to encrypt the file. Private key should never be send to anyone outside!

How to start?

Download latest version of GnuPG from www.gnupg.org

General Help

gpg --help

Creating public/private(secret) key

gpg --gen-key

Listing public/private keys

gpg --list-keys

Exporting public key

gpg --armor --export test@email > public.key

Exporting private key

gpg --armor –export-secret-key test@email > public.key

Importing keys

gpg -–import key.txt

Deleting secret key

gpg --delete-secret-keys test@email

Deleting public key

gpg --delete-keys test@email

Change passphrase

gpg --edit-key test@email passwd

Encrypt file

gpg --batch --output "<outfile>" --encrypt --recipient test@email "<infile>"

Encrypt file with different cipher algorithm

gpg --batch --output "<outfile>" --encrypt --cipher-algo AES --recipient test@email "<infile>"

Decrypt file

gpg --batch --output "<outfile>" --decrypt "<infile>"

Monday, 26 October 2009

Update/Insert data from one table to another

create TABLE #Load(
id int,
[name] VARCHAR(20)
)

create table #Data(
id int,
[name] VARCHAR(20)
)

SELECT * FROM #Data

INSERT INTO #Load
SELECT 1,'one'
UNION SELECT 2,'two'

UPDATE dbo.#Data SET
[name]=l.[name]
FROM #Load l JOIN #Data i ON l.id = i.id

INSERT INTO #Data
SELECT l.* FROM #Load l
LEFT JOIN #Data i ON i.id = l.id
WHERE i.id IS NULL

SELECT * FROM #Data

DELETE FROM #Load

INSERT INTO #Load
SELECT 2,'updated two'
UNION SELECT 3,'three'

UPDATE dbo.#Data SET
[name]=l.[name]
FROM #Load l JOIN #Data i ON l.id = i.id

INSERT INTO #Data
SELECT l.* FROM #Load l
LEFT JOIN #Data i ON i.id = l.id
WHERE i.id IS NULL

SELECT * FROM #Data

DROP TABLE #Load
DROP TABLE #Data

Thursday, 15 October 2009

Resolving DLL version conflict

If you’re using a third party library which was compiled with old version of some common library (like log4net) you will get a dll conflict when you try to run it.

.Net allows you to do binding redirect in App.config as long as the publicKeyToken is the same between versions.

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="CommonLibrary" publicKeyToken="b32731d11ce58905" culture="neutral" />
<bindingRedirect oldVersion="1.0.0.1" newVersion="1.0.0.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>

How to find public key for .NET dll or exe

  • Open Visual Studio Command Prompt
  • Run sn program as below

C:\>sn –T C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Accessibility.dll

Microsoft (R) .NET Framework Strong Name Utility  Version 2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key token is b03f5f7f11d50a3a

Saturday, 10 October 2009

SyncToy v2.0

“SyncToy 2.0 for Windows is available as a free download from the Microsoft Download Center. The easy to use, customizable application helps you copy, move, rename, and delete files between folders and computers.”

Wednesday, 7 October 2009

Visual Studio Subversion plugin

ankhsvn

Monday, 5 October 2009

Moving ClickOnce publish directory

  • Set update location in Visual Studio to the new location in the publish/update section and publish to the old location.
  • Change publish location to new location and publish again.

Fixing Expired ClickOnce Certificate

If certificate expired:

  • Create new certificate (using Visual Studio)
  • Use Renewcert (Method 3) + This code (renewcert.cpp)
  • Create extended certificate (5years)
  • Release App

If certificate is about to expire skip first step