DevTrain

Autor: Till Groos

Zeitliche Beschränkung der Laufzeit von Software

Es gibt einige Möglichkeiten, Software nur für bestimmte Zeit laufen zu lassen. Sie können Einträge zur Registry hinzufügen oder Software schon beim Kompilieren nur bis zu einen bestimmten Datum funktionieren lassen. Einträge in der Registry kann man jedoch ändern und Ihre 30 Tage Testversion wollen Sie auch nicht jede Woche neu kompilieren. Was aber, wenn Ihre Software nur in einer bestimmten Zeitspanne lauffähig sein soll, variable von Ihnen bestimmt und sicher?

Die Lösung hier benutzt den ?System.Security.Cryptography? und den ?System.Runtime.Serialization.Formatters.Binary? Namespace. Die Idee ist, eine Schlüsseldatei zu generieren, welche dann jeweils mit der Software ausgeliefert wird.

Die Vorgehensweise

Da wir es sicher machen wollen, definieren wir uns eine eigene Struktur ?Zeitspanne?, die die Zeitspanne repräsentiert.

[Serializable]
 public struct Zeitspanne : ISerializable
 {
  public long s, e;
  public Zeitspanne(long s, long e)
  {
   this.s = s;
   this.e = e;
  }
  public Zeitspanne(SerializationInfo info, StreamingContext context)
  {
   s = info.GetInt64("s");
   e = info.GetInt64("e");
  }
  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
   info.AddValue("s", s);
   info.AddValue("e", e);
  }

 }

Um diese Datei vor Bösewichtern zu Schützen, verschlüsseln wir unsere Daten noch mit dem RijndaelManaged-Verfahren. Dazu brauchen wir eine Instanz der Klasse ?RijndaelManaged, ein Byte-Array als geheimen Schlüssel und ein Byte-Array als Vektor zur Verschlüsselung.
Aber nicht genug der Sicherheit. Wir serialisieren unsere ?TimeSpan? auch binär, was in Kombination mit der Verschlüsselung wohl sicher genug sein sollte.

Hier der ganze Code zur Verschlüsselung (VB.NET)

Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Security.Cryptography

?Die Zeitspanne
Dim mySpan As New Zeitspanne(Me.dtpStart.Value.Ticks, Me.dtpStop.Value.Ticks)
?Unsere Verschlüsselungsmethode
Dim RMCrypto As New RijndaelManaged
?GEHEIM
Dim Key As Byte() = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
?init Verktor
Dim IV As Byte() = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}
?hilfsstream
Dim s As New MemoryStream
?der eigentliche Stream zum Verschlüsseln
Dim CryptStream As New CryptoStream(New FileStream("key.bin", FileMode.OpenOrCreate), RMCrypto.CreateEncryptor(Key, IV),  CryptoStreamMode.Write)

?Zum Serialisieren
Dim b As BinaryFormatter = New BinaryFormatter
Try
       ?erst Serialisieren
       b.Serialize(s, mySpan)
       ?dann den Inhalt verschlüsseln
       For i As Int32 = 0 To s.ToArray.Length - 1
           CryptStream.WriteByte(s.ToArray(i))
       Next
       MessageBox.Show("Keyfile generiert", "Bestätigung")
Catch ex As Exception
       MessageBox.Show(ex.ToString, ex.GetType.ToString)
Finally
       CryptStream.Flush()
       CryptStream.Close()
       s.Flush()
       s.Close()
End Try

Um das ganze wieder auszulesen, muss man alle Schritte rückwärts ausführen. Ein Sache muss man noch wissen: der BinaryFormatter kann nur aus einer Datei deserialisieren. Deshalb muss man der Cryptostream erst in eine temporäre Datei Zwischenspeichern. Leider ist dies eine ziemliche Schwachstelle in unserem Sicherheitssystem. Trotz intensiven Bemühens funktionierte das Deserialisieren nicht aus dem MemoryStream. Hier jetzt der Code (C#)

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

//aktuelles Datum
long jetzt;
// unsere Zeitspanne
Zeitspanne mySpan;
RijndaelManaged RMCrypto = new RijndaelManaged();
byte[] Key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte[] IV = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
Stream s = File.Open(@"key.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
jetzt = s.Length;
CryptoStream CryptStream = new CryptoStream(s,
RMCrypto.CreateDecryptor(Key, IV),
CryptoStreamMode.Read);
MemoryStream m = new MemoryStream();
int input=0;
while(input != -1)
{
 input = CryptStream.ReadByte();
 if (input == -1)
 { 
  break;
 }
 m.WriteByte(Convert.ToByte(input));
 m.Flush();
}
Stream fs = File.Open(@"tmp.str", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
m.WriteTo(fs);
m.Flush();
m.Close();
fs.Close();
Stream ms = File.Open(@"tmp.str", FileMode.Open, FileAccess.Read, FileShare.Read);
BinaryFormatter bf = new BinaryFormatter();
mySpan = (Zeitspanne)bf.Deserialize(ms);
jetzt = DateTime.Now.Ticks;
if((mySpan.s <= jetzt) & (jetzt <= mySpan.e))
{
 this.Visible=true;
}
else
{
 Response.Redirect("fehler.aspx");
}
ms.Close();
s.Close();
CryptStream.Close();


Erfasst am: 27.01.2004 - Artikel-URL: http://www.devtrain.de/news.aspx?artnr=907
© Copyright 2003 ppedv AG - http://www.ppedv.de