´╗┐Imports System
Imports System.Text
Imports System.Diagnostics
Imports System.IO
Imports Sc14n

'  
' * $Id: TestSc14n.vb $
' * Last updated:
' *   $Date: 2017-07-15 16:23 $
' *   $Version: 0.9.0a $
' 

' Some tests using the SC14N .NET interface.
' * 
' * Requires `Sc14n` to be installed on your system: available from <http://di-mgt.com.au/sc14n/>
' * Add a reference to `diSc14nNet.dll`
' * 
' * Test files, e.g. `olamundo.xml`, are in `sc14n-testfiles.zip`. These must be in the CWD.
' * 
' * This is a Console Application written for target .NET Framework 2.0 and above 
' * Please report any bugs to <http://www.di-mgt.com.au/contact>
' 

'****************************** LICENSE ***********************************
' * Copyright (C) 2017 David Ireland, DI Management Services Pty Limited.
' * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net>
' * The code in this module is licensed under the terms of the MIT license.  
' * For a copy, see <http://opensource.org/licenses/MIT>
'****************************************************************************
'


' Ported from C# to VB.NET using icsharpcode.net's SharpDevelop.

Namespace TestSc14nNet
  Class TestSc14nNet
    Public Shared Sub Main(args As String())
      Dim n As Integer, r As Integer
      Dim s As String, fname As String, oname As String, digval As String, digval1 As String
      Dim b As Byte()

      ' SHOW GENERAL INFO ABOUT THE CORE LIBRARY DLL
      n = Gen.Version()
      Console.WriteLine("Version={0}", n)
      Console.WriteLine("Platform={0}", Gen.Platform())
      Console.WriteLine("ModuleName={0}", Gen.ModuleName())
      Console.WriteLine("CompileTime={0}", Gen.CompileTime())
      Console.WriteLine("LicenceType={0}", Gen.LicenceType())


      ' DO TESTS ON INPUT.XML (these are from the manual)

      Console.WriteLine("FILE: {0}", "input.xml")

      ' Example 1. Excludes the first element with the tag name <Signature>
      r = C14n.ToFile("c14nfile1.txt", "input.xml", "Signature", Tran.ExcludeByTag)
      Debug.Assert(0 = r, "C14n.ToFile failed")

      ' Example 2. Finds and transforms the first element with the tag name <SignedInfo>
      r = C14n.ToFile("c14nfile2.txt", "input.xml", "SignedInfo", Tran.SubsetByTag)
      Debug.Assert(0 = r, "C14n.ToFile failed")

      ' Example 3. Finds and transforms the third element with the tag name <Data>
      r = C14n.ToFile("c14nfile3.txt", "input.xml", "Data[3]", Tran.SubsetByTag)
      Debug.Assert(0 = r, "C14n.ToFile failed")

      ' Example 4. Finds and transforms the element with attribute Id="foo"
      r = C14n.ToFile("c14nfile4.txt", "input.xml", "foo", Tran.SubsetById)
      Debug.Assert(0 = r, "C14n.ToFile failed")

      ' Example 5. Finds and transforms the element with attribute ID="bar"
      r = C14n.ToFile("c14nfile5.txt", "input.xml", "ID=bar", Tran.SubsetById)
      Debug.Assert(0 = r, "C14n.ToFile failed")

      ' Example 6. Excludes element with attribute Id="thesig"
      r = C14n.ToFile("c14nfile6.txt", "input.xml", "thesig", Tran.ExcludeById)
      Debug.Assert(0 = r, "C14n.ToFile failed")


      ' REDO LAST TESTS BUT COMPUTE DIGEST INSTEAD OF CREATING NEW FILE

      ' Example 1. Excludes the first element with the tag name <Signature>
      digval = C14n.ToDigest("input.xml", "Signature", Tran.ExcludeByTag, DigAlg.Sha1)
      Console.WriteLine("DIG1={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      ' Example 2. Finds and transforms the first element with the tag name <SignedInfo>
      digval = C14n.ToDigest("input.xml", "SignedInfo", Tran.SubsetByTag, DigAlg.Sha1)
      Console.WriteLine("DIG2={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      ' Example 3. Finds and transforms the third element with the tag name <Data>
      digval = C14n.ToDigest("input.xml", "Data[3]", Tran.SubsetByTag, DigAlg.Sha1)
      Console.WriteLine("DIG3={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      ' Example 4. Finds and transforms the element with attribute Id="foo"
      digval = C14n.ToDigest("input.xml", "foo", Tran.SubsetById, DigAlg.Sha1)
      Console.WriteLine("DIG4={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      ' Example 5. Finds and transforms the element with attribute ID="bar"
      digval = C14n.ToDigest("input.xml", "ID=bar", Tran.SubsetById, DigAlg.Sha1)
      Console.WriteLine("DIG5={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      ' Example 6. Excludes element with attribute Id="thesig"
      digval = C14n.ToDigest("input.xml", "thesig", Tran.ExcludeById, DigAlg.Sha1)
      Console.WriteLine("DIG6={0}", digval)
      Debug.Assert(digval.Length > 0, "C14n.ToDigest failed")

      Console.WriteLine("NOTE: Should have DIG1==DIG6 and DIG3==DIG4 above.")

      ' Transform entire file
      fname = "olamundo.xml"
      oname = "olamundo-out.xml"
      Console.WriteLine("FILE: {0}", fname)
      n = C14n.ToFile(oname, fname)
      Console.WriteLine("C14n.ToFile()->{0} returns {1} (expected 0 => OK)", oname, n)
      Debug.Assert(0 = n, "C14n.ToFile failed")

      ' Compute digest of entire file
      digval = C14n.ToDigest(fname, 0)
      Console.WriteLine("C14n.ToDigest({0})={1}", fname, digval)
      ' and do the same to the transformed file we made above
      digval1 = C14n.ToDigest(oname, 0)
            Console.WriteLine("C14n.ToDigest({0})={1}", oname, digval1)
      Debug.Assert(digval = digval1)

      ' Same data, different encoding plus UTF-8 Byte Order Mark
      fname = "olamundo-utf8bom.xml"
      oname = "olamundo-utf8bom-out.xml"
      Console.WriteLine("FILE: {0}", fname)
      digval = C14n.ToDigest(fname, 0)
      Console.WriteLine("C14n.ToDigest({0})={1}", fname, digval)

      ' -- we can transform (X)HTML files, too. 
      ' This example is used in a detached signature: see `detached.xml`
      fname = "abc.html"
      oname = "abc-c14n-html.txt"
      Console.WriteLine("FILE: {0}", fname)
      n = C14n.ToFile(oname, fname)
      Console.WriteLine("C14n.ToFile()->{0} returns {1} (expected 0 => OK)", oname, n)
      If n <> 0 Then
        Console.WriteLine(displayError(n))
      End If
      Debug.Assert(0 = n, "C14n.ToFile failed")
      ' Display entire file after transforming...
      s = System.Text.Encoding.UTF8.GetString(C14n.ToBytes(fname))
      Console.WriteLine("C14N('{0}'):", fname)
      Console.WriteLine(s)

      ' Compute SHA-1 digest of entire file
      digval = C14n.ToDigest(fname, 0)
      Console.WriteLine("C14n.ToDigest({0})={1}", fname, digval)
      ' and do the same to the transformed file we made above
      digval1 = C14n.ToDigest(oname, 0)
            Console.WriteLine("C14n.ToDigest({0})={1}", oname, digval1)
      Debug.Assert(digval = digval1)

      ' Same again but using SHA-256
      digval = C14n.ToDigest(fname, DigAlg.Sha256)
      Console.WriteLine("SHA256('{0}'): {1}", fname, digval)

      ' Extract and transform the body element
      ' Output to a byte array
      fname = "olamundo-base.xml"
      Console.WriteLine("FILE: {0}", fname)
      b = C14n.ToBytes(fname, "Body", Tran.SubsetByTag)
      Debug.Assert(b.Length > 0, "C14n.ToBytes failed")
      Console.WriteLine("C14n.ToBytes(SubsetByTag) returns {0} bytes.", b.Length)
      ' Note this a byte array containing UTF-8-encoded text, so be careful printing
      Console.WriteLine("C14N(Body):")
      Console.WriteLine(System.Text.Encoding.UTF8.GetString(b))

      ' Compute SHA-1 digest value of the XML document excluding the <Signature> element
      ' ... this is the value to be inserted into <SignedInfo>
      digval = C14n.ToDigest(fname, "Signature", Tran.ExcludeByTag, DigAlg.Sha1)
      Console.WriteLine("DIGVAL:")
      Console.WriteLine(digval)

      ' Extract the SignedInfo element into memory
      ' Note %digval% parameter to be completed
      b = C14n.ToBytes(fname, "SignedInfo", Tran.SubsetByTag)
      Debug.Assert(b.Length > 0, "C14n.ToBytes failed")
      Console.WriteLine("SIGNEDINFO (BASE):")
      Console.WriteLine(System.Text.Encoding.UTF8.GetString(b))

      ' Insert the required DigestValue we prepared earlier
      ' Note the SignedInfo element is *always* US-ASCII encoded,
      ' so we can use the more convenient String.Replace function
      s = System.Text.Encoding.UTF8.GetString(b).Replace("%digval%", digval)
      Console.WriteLine("SIGNEDINFO (COMPLETED):")
      Console.WriteLine(s)
      ' Now compute the digest value of this string
      ' We could use this to compute the required signature value.
      ' See the module `TestScn14PKI` for a full example using a cryptographic library.
      digval1 = C14n.ToDigest(System.Text.Encoding.UTF8.GetBytes(s), DigAlg.Sha1)
      Console.WriteLine("SHA1(signedinfo)= {0}", digval1)


      Console.WriteLine(vbLf & "ALL DONE.")

    End Sub

    ''' <summary>
    ''' Display last error status
    ''' </summary>
    ''' <param name="errCode">Error code (+ve or -ve)</param>
    ''' <returns>String containing error status</returns>
    Private Shared Function displayError(errCode As Integer) As String
      Dim se As String = Err.LastError()
      Dim s As String = String.Format("ERROR {0}: ", (If(errCode < 0, -errCode, errCode)))
      s += Err.ErrorLookup(errCode)
      If se.Length > 0 Then
        s += ": " & se
      End If
      Return s
    End Function
  End Class
End Namespace