public enum DicomTlsCipherSuiteType
Public Enum DicomTlsCipherSuiteType
public enum class DicomTlsCipherSuiteType
Value | Member | Description |
---|---|---|
0 | None | No cipher suite has been agreed upon yet. |
18 | DheRsaWithDesCbcSha | (Deprecated do not use) TLS_RSA_WITH_DES_CBC_SHA |
19 | DheRsaWith3DesEdeCbcSha | (Deprecated do not use) TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA |
20 | DheRsaAes256Sha | (Deprecated do not use) DHE_RSA_AES_256_SHA (SSL3) |
21 | RsaWithAes128CbcSha | TLS_RSA_WITH_AES_128_CBC_SHA (TLS 1.0) |
22 | RsaWith3DesEdeCbcSha | TLS_RSA_WITH_3DES_EDE_CBC_SHA (TLS 1.0) |
23 | DheRsaWithAes128GcmSha256 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (TLS 1.2) |
24 | EcdheRsaWithAes128GcmSha256 | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (TLS 1.2) |
25 | DheRsaWithAes256GcmSha384 | TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (TLS 1.2) |
26 | EcdheRsaWithAes256GcmSha384 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (TLS 1.2) |
Currently, only the cipher suites listed are supported by LEADTOOLS.
This is a comprehensive sample that shows how to use DICOM Secure communication using TLS.
using Leadtools;
using Leadtools.Dicom;
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
}
public enum WaitReturn
{
Complete,
Timeout,
}
class Utils
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd,
uint wMsgFilterMin, uint wMsgFilterMax,
uint wRemoveMsg);
[DllImport("user32.dll")]
static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
const uint PM_REMOVE = 1;
public static WaitReturn WaitForComplete(double mill, WaitHandle wh)
{
TimeSpan goal = new TimeSpan(DateTime.Now.AddMilliseconds(mill).Ticks);
do
{
MSG msg = new MSG();
if (PeekMessage(out msg, IntPtr.Zero, 0, 0, PM_REMOVE))
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
if (wh.WaitOne(new TimeSpan(0, 0, 0), false))
{
return WaitReturn.Complete;
}
if (goal.CompareTo(new TimeSpan(DateTime.Now.Ticks)) < 0)
{
return WaitReturn.Timeout;
}
} while (true);
}
public static void SetupTlsContext(DicomNet net, string certName)
{
string serverCA = Path.Combine(LEAD_VARS.ImagesDir, "ca.pem");
if (net != null)
{
DicomOpenSslContextCreationSettings settings = new DicomOpenSslContextCreationSettings(
DicomSslMethodType.SslV23,
serverCA,
DicomOpenSslVerificationFlags.Peer | DicomOpenSslVerificationFlags.FailIfNoPeerCertificate,
2,
DicomOpenSslOptionsFlags.NoSslV2 | DicomOpenSslOptionsFlags.AllBugWorkarounds
);
net.Initialize(null, DicomNetSecurityMode.Tls, settings);
net.SetTlsClientCertificate(certName, DicomTlsCertificateType.Pem, null);
}
}
}
//
// Secure client (TLS)
//
class Client : DicomNet
{
AutoResetEvent waitEvent = new AutoResetEvent(false);
string clientPEM = Path.Combine(LEAD_VARS.ImagesDir, "client.pem");
public Client()
: base(null, DicomNetSecurityMode.Tls)
{
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWithDesCbcSha);
Utils.SetupTlsContext(this, clientPEM);
}
public bool Wait()
{
WaitReturn ret;
ret = Utils.WaitForComplete((5 * 60) * 1000, waitEvent);
return (ret == WaitReturn.Complete);
}
protected override void OnConnect(DicomExceptionCode error)
{
waitEvent.Set();
}
protected override string OnPrivateKeyPassword(bool encryption)
{
return "test";
}
protected override void OnSecureLinkReady(DicomExceptionCode error)
{
waitEvent.Set();
}
}
//
// Secure server (TLS)
//
class ServerConnection : DicomNet
{
string serverPEM = Path.Combine(LEAD_VARS.ImagesDir, "server.pem");
public ServerConnection()
: base(null, DicomNetSecurityMode.Tls)
{
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWith3DesEdeCbcSha);
SetTlsClientCertificate(serverPEM, DicomTlsCertificateType.Pem, null);
}
protected override string OnPrivateKeyPassword(bool encryption)
{
return "test";
}
// The OnVerify callback gets called twice, once for each certificate in the certificate chain.
protected override int OnVerify(int ok, string certificateString, DicomSecurityCertificateException ex)
{
string certificateMessageString = "Received Client Certificate:\n" + certificateString;
// Log that the SCP received the Client Certificate
Debug.WriteLine(certificateMessageString);
if (ex.Code != DicomSecurityCertificateExceptionCode.Success)
{
string message = string.Format("Error {0}: {1}", ex.Code, ex.Message);
// Log the error with Client Certificate
Debug.WriteLine(message);
}
return ok;
}
}
class Server : DicomNet
{
string serverPEM = Path.Combine(LEAD_VARS.ImagesDir, "server.pem");
ServerConnection client;
public Server()
: base(null, DicomNetSecurityMode.Tls)
{
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWith3DesEdeCbcSha);
Utils.SetupTlsContext(this, serverPEM);
}
protected override void OnAccept(DicomExceptionCode error)
{
client = new ServerConnection();
Utils.SetupTlsContext(client, serverPEM);
Accept(client);
}
protected override string OnPrivateKeyPassword(bool encryption)
{
return "test";
}
protected override void Dispose(bool __p1)
{
client.Dispose();
base.Dispose(__p1);
}
}
public void TLSSecuritySample()
{
//Assert test to check file exists before running code
string clientPEM = Path.Combine(LEAD_VARS.ImagesDir, "ca.pem");
Assert.IsTrue(File.Exists(clientPEM) == true, "Missing file: " + clientPEM);
DicomEngine.Startup();
DicomNet.Startup();
using (Server server = new Server())
{
using (Client client = new Client())
{
server.Listen("127.0.0.1", 104, 1); // start server
client.Connect(null, 1000, "127.0.0.1", 104); // connect to server
if (!client.Wait()) // wait for connection to finish
{
Debug.Fail("Connection timed out");
}
Debug.Assert(client.IsConnected(), "Client not connected");
//
// Wait for authenication
//
if (!client.Wait())
{
Debug.Fail("Connection timed out waiting for authenication");
}
// Once two computers have negotiated the ciphersuite, and have
// authenticated each other, they can begin transferring
// messages and data between them.
//Now we can get detailed information about the Cipher Suite
DicomTlsCipherSuiteType cipherSuite = client.GetTlsCipherSuite();// Can also call GetTlsCipherSuiteByIndex
Debug.WriteLine("Encryption Algorithm is : {0}", client.GetTlsEncryptionAlgorithm(cipherSuite));
Debug.WriteLine("Authentication Algorithm is : {0}", client.GetTlsAuthenticationAlgorithm(cipherSuite));
Debug.WriteLine("Integrity Algorithm is : {0}", client.GetTlsIntegrityAlgorithm(cipherSuite));
Debug.WriteLine("Key Exchange Algorithm is : {0}", client.GetTlsKeyExchangeAlgorithm(cipherSuite));
Debug.WriteLine("Encryption Key Length is : {0}", client.GetTlsEncryptionKeyLength(cipherSuite));
Debug.WriteLine("Mutual Authentication Key Length is : {0}", client.GetTlsMutualAuthenticationKeyLength(cipherSuite));
// Continue with normal dicom communication
client.CloseForced(true);
}
server.CloseForced(true);
}
DicomEngine.Shutdown();
DicomNet.Shutdown();
}
static class LEAD_VARS
{
public const string ImagesDir = @"C:\LEADTOOLS21\Resources\Images";
}
Imports Leadtools
Imports Leadtools.Dicom
<StructLayout(LayoutKind.Sequential)>
Public Structure MSG
Public hwnd As IntPtr
Public message As UInteger
Public wParam As IntPtr
Public lParam As IntPtr
Public time As UInteger
Public p As System.Drawing.Point
End Structure
Public Enum WaitReturn
Complete
Timeout
End Enum
Private Class Utils
<DllImport("user32.dll")>
Shared Function PeekMessage(<System.Runtime.InteropServices.Out()> ByRef lpMsg As MSG, ByVal hWnd As IntPtr, ByVal wMsgFilterMin As UInteger,
ByVal wMsgFilterMax As UInteger, ByVal wRemoveMsg As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll")>
Shared Function TranslateMessage(ByRef lpMsg As MSG) As Boolean
End Function
<DllImport("user32.dll")>
Shared Function DispatchMessage(ByRef lpmsg As MSG) As IntPtr
End Function
Private Const PM_REMOVE As UInteger = 1
Public Shared Function WaitForComplete(ByVal mill As Double, ByVal wh As WaitHandle) As WaitReturn
Dim goal As TimeSpan = New TimeSpan(DateTime.Now.AddMilliseconds(mill).Ticks)
Do
Dim msg As MSG = New MSG()
If PeekMessage(msg, IntPtr.Zero, 0, 0, PM_REMOVE) Then
TranslateMessage(msg)
DispatchMessage(msg)
End If
If wh.WaitOne(New TimeSpan(0, 0, 0), False) Then
Return WaitReturn.Complete
End If
If goal.CompareTo(New TimeSpan(DateTime.Now.Ticks)) < 0 Then
Return WaitReturn.Timeout
End If
Loop While True
End Function
Public Shared Sub SetupTlsContext(ByVal net As DicomNet, ByVal certName As String)
Dim serverCA As String = Path.Combine(LEAD_VARS.ImagesDir, "ca.pem")
If net IsNot Nothing Then
Dim settings As New DicomOpenSslContextCreationSettings(DicomSslMethodType.SslV23, serverCA, DicomOpenSslVerificationFlags.Peer Or DicomOpenSslVerificationFlags.FailIfNoPeerCertificate, 2, DicomOpenSslOptionsFlags.NoSslV2 Or DicomOpenSslOptionsFlags.AllBugWorkarounds)
net.Initialize(Nothing, DicomNetSecurityMode.Tls, settings)
net.SetTlsClientCertificate(certName, DicomTlsCertificateType.Pem, Nothing)
End If
End Sub
End Class
'
' Secure client (TLS)
'
Private Class Client : Inherits DicomNet
Private waitEvent As AutoResetEvent = New AutoResetEvent(False)
Private clientPEM As String = Path.Combine(LEAD_VARS.ImagesDir, "client.pem")
Public Sub New()
MyBase.New(Nothing, DicomNetSecurityMode.Tls)
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWithDesCbcSha)
Utils.SetupTlsContext(Me, clientPEM)
End Sub
Public Function Wait() As Boolean
Dim ret As WaitReturn
ret = Utils.WaitForComplete((5 * 60) * 1000, waitEvent)
Return (ret = WaitReturn.Complete)
End Function
Protected Overrides Sub OnConnect(ByVal [error] As DicomExceptionCode)
waitEvent.Set()
End Sub
Protected Overrides Function OnPrivateKeyPassword(ByVal encryption As Boolean) As String
Return "test"
End Function
Protected Overrides Sub OnSecureLinkReady(ByVal [error] As DicomExceptionCode)
waitEvent.Set()
End Sub
End Class
'
' Secure server (TLS)
'
Private Class ServerConnection : Inherits DicomNet
Private serverPEM As String = Path.Combine(LEAD_VARS.ImagesDir, "server.pem")
Public Sub New()
MyBase.New(Nothing, DicomNetSecurityMode.Tls)
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWith3DesEdeCbcSha)
SetTlsClientCertificate(serverPEM, DicomTlsCertificateType.Pem, Nothing)
End Sub
Protected Overrides Function OnPrivateKeyPassword(ByVal encryption As Boolean) As String
Return "test"
End Function
End Class
Private Class Server : Inherits DicomNet
Private serverPEM As String = Path.Combine(LEAD_VARS.ImagesDir, "server.pem")
Private client As ServerConnection
Public Sub New()
MyBase.New(Nothing, DicomNetSecurityMode.Tls)
SetTlsCipherSuiteByIndex(0, DicomTlsCipherSuiteType.DheRsaWith3DesEdeCbcSha)
Utils.SetupTlsContext(Me, serverPEM)
End Sub
Protected Overrides Sub OnAccept(ByVal [error] As DicomExceptionCode)
client = New ServerConnection()
Utils.SetupTlsContext(client, serverPEM)
Accept(client)
End Sub
Protected Overrides Function OnPrivateKeyPassword(ByVal encryption As Boolean) As String
Return "test"
End Function
Protected Overloads Overrides Sub Dispose(ByVal __p1 As Boolean)
client.Dispose()
MyBase.Dispose(__p1)
End Sub
End Class
Public Sub TLSSecuritySample()
DicomEngine.Startup()
DicomNet.Startup()
Using server As Server = New Server()
Using client As Client = New Client()
server.Listen("127.0.0.1", 104, 1) ' start server
client.Connect(Nothing, 1000, "127.0.0.1", 104) ' connect to server
If (Not client.Wait()) Then ' wait for connection to finish
Debug.Fail("Connection timed out")
End If
Debug.Assert(client.IsConnected(), "Client not connected")
'
' Wait for authenication
'
If (Not client.Wait()) Then
Debug.Fail("Connection timed out waiting for authenication")
End If
' Once two computers have negotiated the ciphersuite, and have
' authenticated each other, they can begin transferring
' messages and data between them.
'Now we can get detailed information about the Cipher Suite
Dim cipherSuite As DicomTlsCipherSuiteType = client.GetTlsCipherSuite() ' Can also call GetTlsCipherSuiteByIndex
Debug.WriteLine("Encryption Algorithm is : {0}", client.GetTlsEncryptionAlgorithm(cipherSuite))
Debug.WriteLine("Authentication Algorithm is : {0}", client.GetTlsAuthenticationAlgorithm(cipherSuite))
Debug.WriteLine("Integrity Algorithm is : {0}", client.GetTlsIntegrityAlgorithm(cipherSuite))
Debug.WriteLine("Key Exchange Algorithm is : {0}", client.GetTlsKeyExchangeAlgorithm(cipherSuite))
Debug.WriteLine("Encryption Key Length is : {0}", client.GetTlsEncryptionKeyLength(cipherSuite))
Debug.WriteLine("Mutual Authentication Key Length is : {0}", client.GetTlsMutualAuthenticationKeyLength(cipherSuite))
' Continue with normal dicom communication
client.CloseForced(True)
End Using
server.CloseForced(True)
End Using
DicomEngine.Shutdown()
DicomNet.Shutdown()
End Sub
Public NotInheritable Class LEAD_VARS
Public Const ImagesDir As String = "C:\LEADTOOLS21\Resources\Images"
End Class
GetTlsCipherSuiteByIndex Method
SetTlsCipherSuiteByIndex Method
GetTlsEncryptionAlgorithm Method
GetTlsAuthenticationAlgorithm Method
GetTlsIntegrityAlgorithm Method
GetTlsKeyExchangeAlgorithm Method
Help Collections
Raster .NET | C API | C++ Class Library | HTML5 JavaScript
Document .NET | C API | C++ Class Library | HTML5 JavaScript
Medical .NET | C API | C++ Class Library | HTML5 JavaScript
Medical Web Viewer .NET
Multimedia
Direct Show .NET | C API | Filters
Media Foundation .NET | C API | Transforms
Supported Platforms
.NET, Java, Android, and iOS/macOS Assemblies
Imaging, Medical, and Document
C API/C++ Class Libraries
Imaging, Medical, and Document
HTML5 JavaScript Libraries
Imaging, Medical, and Document