Avatar billede Slettet bruger
05. januar 2006 - 15:01 Der er 8 kommentarer og
1 løsning

Eget serial nummer system

Hej Eksperter,
Jeg har brug for noget hjælpe til hvordan man laver egne serials, dem jeg skal bruge skal eks se sådan ud:

x23-xx424x42

Altså både bogstaver og tal, jeg skal kunne gemme en egenskab i serial'en - så jeg kan få at vide om det er et standard password eller et enterprise password - eks. Det kunne bare være et nummer 0-9 hvor 0 er standard og 1 er enterprise.. eks.

Det er ikke så vigtigt at det ligner mit eks. men det er vigtigt at man på klientsiden kan se om serialen er valid og hvilken egenskab det har.

Håber i kan komme med nogle eksempler - tak! Gerne til .net 2.0
Avatar billede Slettet bruger
05. januar 2006 - 15:02 #1
- er bare for at opdele det i 2 grupper, det skal ikke fortolkes som et tegn der er med i serial'en.
Avatar billede nielle Nybegynder
05. januar 2006 - 21:08 #2
Du kan jo prøve at kigge lidt på dette eksempel:

using System;
using System.Text;
using System.Security.Cryptography;

namespace e677103
{
    class SerialNo
    {
        private const string password = "password";

        static public string Generate(string message)
        {
            string obfuscatedMessage = Obfuscate(message);
            byte[] encryptedMessage = Encrypt(obfuscatedMessage);
            return Base64Encode(encryptedMessage);
        }

        static public string Retrieve(string message)
        {
            byte[] decodedMessage = Base64Decode(message);
            if (decodedMessage == null) return "";
            string decryptedMessage = Decrypt(decodedMessage);
            return DeObfuscate(decryptedMessage);
        }
                   
        static private string Obfuscate(string message)
        {
            Random fate = new Random();

            StringBuilder obfuscatedMessage = new StringBuilder();

            for (int idx = 0; idx < Math.Max(message.Length, 10); idx++)
            {
                obfuscatedMessage.Append(fate.Next(0, 10).ToString());

                if (idx < message.Length)
                    obfuscatedMessage.Append(message[idx]);
                else
                    obfuscatedMessage.Append(".");
            }

            return obfuscatedMessage.ToString();
        }

        static private string DeObfuscate(string message)
        {
            StringBuilder deObfuscatedMessage = new StringBuilder();

            for (int idx=1; idx<message.Length; idx+=2)
            {
                deObfuscatedMessage.Append(message[idx]);
            }

            return deObfuscatedMessage.ToString().TrimEnd('.');
        }

        static private byte[] Encrypt(string message)
        {
            Encoding encoder = new UTF8Encoding();

            byte[] key = encoder.GetBytes(password);
            byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
            Rijndael aes = new RijndaelManaged();
            ICryptoTransform encrypter = aes.CreateEncryptor(key, iv);

            return encrypter.TransformFinalBlock(encoder.GetBytes(message), 0, encoder.GetByteCount(message));
        }

        static private string Decrypt(byte[] message)
        {
            Encoding encoder = new UTF8Encoding();

            byte[] key = encoder.GetBytes(password);
            byte[] iv = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
            Rijndael aes = new RijndaelManaged();
            ICryptoTransform decrypter = aes.CreateDecryptor(key, iv);

            return encoder.GetString(decrypter.TransformFinalBlock(message, 0, message.Length));
        }

        static private string Base64Encode(byte[] message)
        {
            return Convert.ToBase64String(message);
        }



        static private byte[] Base64Decode(string message)
        {
            try
            {
                return Convert.FromBase64String(message);
            }
            catch (System.FormatException)
            {
                return null;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string secretMessage = "Enterprise";
            Console.WriteLine("Input  : " + secretMessage);

            string serialNo = SerialNo.Generate(secretMessage);
            Console.WriteLine("SN    : " + serialNo);

            string validateSecretMessage = SerialNo.Retrieve(serialNo);
            Console.WriteLine("Output : " + validateSecretMessage);
        }
    }
}
Avatar billede Slettet bruger
06. januar 2006 - 11:14 #3
Kan man styre længden lidt mere? ville helst have et på maks 10-12 cifre og så må det kun indeholde tal og bogstaver ikke tegn. Tak
Avatar billede nielle Nybegynder
07. januar 2006 - 20:35 #4
Hvad så med dette her?

using System;

namespace e677103b
{
    enum Egenskab { NotValid = -1, Standard = 3, Enterprise = 5, Dummy = 13 };

    class SerialNo
    {
        private static Random fate = new Random();
        private static int[] digitWeight = { 4, 3, 2, 7, 6, 5, 4, 3, 2, 1 };

        public static string Generate(Egenskab egenskab)
        {
            int[] digit = new int[10];

            while (true)
            {
                // Modulus-11 algoritmen. Bruges bl.a. i CPR numre:
                // http://www.cpr.dk/Index/dokumenter.asp?o=11&n=0&h=11&t=1&d=396&s=4
                while (true)
                {
                    for (int digitNo = 0; digitNo < 9; digitNo++)
                    {
                        digit[digitNo] = (digitNo == 0) ? fate.Next(1, 10) : fate.Next(0, 10);
                    }

                    int summedWeight = 0;
                    for (int digitNo = 0; digitNo < 9; digitNo++)
                    {
                        summedWeight += digit[digitNo] * digitWeight[digitNo];
                    }

                    int controlDigit = 11 - summedWeight % 11;
                    if (controlDigit < 10)
                    {
                        digit[9] = controlDigit;
                        break;
                    }
                }

                // Konvertering fra int-array til et enkelt long.
                long serialNo = 0;
                for (int digitNo = 0; digitNo < 10; digitNo++)
                {
                    serialNo *= 10;
                    serialNo += digit[digitNo];
                }

                // Encoding af egenskab.
                if (serialNo % 13 == (int) egenskab)
                {
                    // Returneres som en hex-værdi.
                    return string.Format("{0:X}", serialNo);
                }
            }
        }

        public static Egenskab Validate(string serialNo)
        {
            long serialNoLong = Convert.ToInt64(serialNo, 16);
            serialNo = serialNoLong.ToString();

            if (serialNo.Length != 10) return Egenskab.NotValid;

            // Modulus-11 algoritmen.
            int summedWeight = 0;
            for (int digitNo = 0; digitNo < 10; digitNo++)
            {
                int digit = int.Parse(serialNo[digitNo].ToString());
                summedWeight += digit * digitWeight[digitNo];
            }
            if (summedWeight % 11 != 0) return Egenskab.NotValid;

            // decoding af egenskab.
            for (Egenskab egenskab = Egenskab.NotValid; egenskab < Egenskab.Dummy; egenskab++)
            {
                if (serialNoLong % 13 == (int) egenskab) return egenskab;
            }

            return Egenskab.NotValid;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Egenskab egenskab = Egenskab.Standard;
            Console.WriteLine(egenskab);

            string serialNo = SerialNo.Generate(egenskab);
            Console.WriteLine(serialNo);

            Egenskab valideretEgenskab = SerialNo.Validate(serialNo);
            Console.WriteLine(valideretEgenskab);
        }
    }
}
Avatar billede Slettet bruger
09. januar 2006 - 11:51 #5
Det ser langt bedre ud, jeg ser på det i aften!
Avatar billede Slettet bruger
09. januar 2006 - 20:41 #6
Hej Nielle,
En hurtig test, så retunerer den ikke altid samme længde?

1D1C38673
1648C8DC4
1EF5A7CF3
C821E281
D83F20AA
1E733770A
18EE43C56
EC6A7676
16EBF2784
749C98E0

Jeg må indrømme at jeg ikke helt har forstået hele koden endnu, men roder stadig med den.
Avatar billede nielle Nybegynder
09. januar 2006 - 23:32 #7
Var det et krav at de skulle være af samme længde?

Algoritmen fungere ved første at generere et tilfældigt 10-cifret tal, altså et tal i intervallet:

1000000000 - 9999999999

Efter et par checks (som jeg kommer tilbage til om lidt) så konverteres det til et hexadecimalt tal, hvilket giver:

3B9ACA00 - 2540BE3FF

altså 8-9 hexadecimale cifre.

Tilbage til de nævnte tjek; De 10 tal genereres godt nok tilfældigt, men hvis de ikke efterfølgende passere 2 forskellige tjek, smides de væk og der forsøges igen indtil at algoritmen har fundet et tal som opfylder begge:

Tjek 1) Modulus-11 algoritmen. Denne bruges bl.a. på vore CPR-numre. Hvis man har et muligt personnummer i hånden så kan man altid beregne modulus-11 tjekket på dette, og hvis personnummeret ikke opfylder dette så er det ikke et lovligt personnummer. Algoritmen er beskrevet i det link til CPR-registeret som jeg har angivet.

Den slags tjek bruges på mange andre typer af numre for at sikre at de er blevet indtastet korrekt (eller at personen ikke forsøger at snyde med et falsk CPR-nummer).

Tjekket bruges i dette tilfælde til at verificere at det er et lovligt serienummer. For resten fejler samtlige dine eksempler modulus-11 tjekket, så du må have kommet til at ødelægge noget et eller andet sted. ;^)

Tjek 1 bruges altså til at validere at det er et lovligt serienummer...

Tjek 2) bruges til at finde den gemte egenskab i tallet.

Hvis du kigger i enum'en så kan du se at ”Standard” har værdien 3, mens at ”Enterprise” er 5. Der er intet som helst magisk ved disse værdier. De kunne lige så godt være 2 og 6 (blot de to værdier er forskellige og ligger i intervallet 0-12). Du kan endda gemme flere værdier end kun 2 ved at tage de andre tal i intervallet i brug!

Når algoritmen har fundet et 10-cifret tal, 3638161833, som opfylder tjek 1, så beregner det værdien:

3638161833 % 13

hvilket altid giver et tal imellem 0 og 12 (det er derfor at det er dette interval!). Tallet ”13” er tilfældigt valgt, primært fordi at det er et primtal og fordi at det er ”primtals-tvilling” til det 11-tal som indgår i modulus-11 algoritmen. Du kan vælge noget andet hvis du vil. :^)

Lad os sige at du ænskede at gemme egenskaben ”Standard ”, altså taller 3, i dit serienummer. Ja så ville du simpelthen gentage algoritmen indtil at du fandt et serienummer som opfylder både tjek 1 og hvor resultatet af regnestykket i tjek 2 giver ”3”. Alle de serienumre som ikke opfylder dette bliver simpelthen smidt væk.

Håber at det kastede lidt lys over det? :^)
Avatar billede Slettet bruger
10. januar 2006 - 09:41 #8
Jo tak, smid et svar, du fortjener de points :o)
Avatar billede nielle Nybegynder
10. januar 2006 - 09:42 #9
Svar :^)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester