Implemented message signature and validation.

This commit is contained in:
antiduh
2014-06-27 01:29:03 +00:00
parent 9310dde83b
commit 85288a9dae
3 changed files with 165 additions and 0 deletions

View File

@@ -256,6 +256,135 @@ namespace NSspi.Contexts
return result;
}
public byte[] MakeSignature( byte[] message )
{
SecurityStatus status = SecurityStatus.InternalError;
SecPkgContext_Sizes sizes;
SecureBuffer dataBuffer;
SecureBuffer signatureBuffer;
SecureBufferAdapter adapter;
if ( this.Initialized == false )
{
throw new InvalidOperationException( "The context is not fully formed" );
}
sizes = QueryBufferSizes();
dataBuffer = new SecureBuffer( new byte[message.Length], BufferType.Data );
signatureBuffer = new SecureBuffer( new byte[sizes.MaxSignature], BufferType.Token );
Array.Copy( message, dataBuffer.Buffer, message.Length );
using ( adapter = new SecureBufferAdapter( new[] { dataBuffer, signatureBuffer } ) )
{
// TODO CER
status = ContextNativeMethods.MakeSignature(
ref this.ContextHandle.rawHandle,
0,
adapter.Handle,
0
);
}
if ( status != SecurityStatus.OK )
{
throw new SSPIException( "Failed to create message signature.", status );
}
byte[] outMessage;
int position = 0;
// Enough room for
// - original message length (4 bytes)
// - signature length (2 bytes)
// - original message
// - signature
outMessage = new byte[4 + 2 + dataBuffer.Length + signatureBuffer.Length];
ByteWriter.WriteInt32_BE( dataBuffer.Length, outMessage, position );
position += 4;
ByteWriter.WriteInt16_BE( (Int16)signatureBuffer.Length, outMessage, position );
position += 2;
Array.Copy( dataBuffer.Buffer, 0, outMessage, position, dataBuffer.Length );
position += dataBuffer.Length;
Array.Copy( signatureBuffer.Buffer, 0, outMessage, position, signatureBuffer.Length );
position += signatureBuffer.Length;
return outMessage;
}
public bool VerifySignature( byte[] signedMessage, out byte[] origMessage )
{
SecurityStatus status = SecurityStatus.InternalError;
SecPkgContext_Sizes sizes;
SecureBuffer dataBuffer;
SecureBuffer signatureBuffer;
SecureBufferAdapter adapter;
if ( this.Initialized == false )
{
throw new InvalidOperationException( "The context is not fully formed." );
}
sizes = QueryBufferSizes();
if ( signedMessage.Length < 2 + 4 + sizes.MaxSignature )
{
throw new ArgumentException( "Input message is too small to possibly fit a valid message" );
}
int position = 0;
int messageLen;
int sigLen;
messageLen = ByteWriter.ReadInt32_BE( signedMessage, 0 );
position += 4;
sigLen = ByteWriter.ReadInt16_BE( signedMessage, position );
position += 2;
dataBuffer = new SecureBuffer( new byte[messageLen], BufferType.Data );
Array.Copy( signedMessage, position, dataBuffer.Buffer, 0, messageLen );
position += messageLen;
signatureBuffer = new SecureBuffer( new byte[sigLen], BufferType.Token );
Array.Copy( signedMessage, position, signatureBuffer.Buffer, 0, sigLen );
position += sigLen;
using ( adapter = new SecureBufferAdapter( new[] { dataBuffer, signatureBuffer } ) )
{
status = ContextNativeMethods.VerifySignature(
ref this.ContextHandle.rawHandle,
adapter.Handle,
0,
0
);
}
if ( status == SecurityStatus.OK )
{
origMessage = dataBuffer.Buffer;
return true;
}
else if ( status == SecurityStatus.MessageAltered ||
status == SecurityStatus.OutOfSequence )
{
origMessage = null;
return false;
}
else
{
throw new SSPIException( "Failed to determine the veracity of a signed message.", status );
}
}
private SecPkgContext_Sizes QueryBufferSizes()
{
SecPkgContext_Sizes sizes = new SecPkgContext_Sizes();

View File

@@ -126,6 +126,24 @@ namespace NSspi.Contexts
int qualityOfProtection
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
[DllImport( "Secur32.dll", EntryPoint = "MakeSignature", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus MakeSignature(
ref RawSspiHandle contextHandle,
int qualityOfProtection,
IntPtr bufferDescriptor,
int sequenceNumber
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.MayFail )]
[DllImport( "Secur32.dll", EntryPoint = "VerifySignature", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus VerifySignature(
ref RawSspiHandle contextHandle,
IntPtr bufferDescriptor,
int sequenceNumber,
int qualityOfProtection
);
[ReliabilityContract( Consistency.WillNotCorruptState, Cer.Success )]
[DllImport( "Secur32.dll", EntryPoint = "QueryContextAttributes", CharSet = CharSet.Unicode )]
internal static extern SecurityStatus QueryContextAttributes_Sizes(

View File

@@ -145,6 +145,24 @@ namespace NSspi
}
cipherText = client.MakeSignature( plainText );
bool goodSig = server.VerifySignature( cipherText, out roundTripPlaintext );
if ( goodSig == false ||
roundTripPlaintext.Length != plainText.Length )
{
throw new Exception();
}
for ( int i = 0; i < plainText.Length; i++ )
{
if ( plainText[i] != roundTripPlaintext[i] )
{
throw new Exception();
}
}
Console.Out.Flush();
}
finally