Question

Is there a existing method within .NET Framework (C#) to generate a 40 char (public?) fingerprint as shown below, when you have P, Q, G, Y and X?

Or would anybody know on how to achieve this?

Fingerprint: 81F68001 29D928AD BEE41B78 AA862106 CAEAC892

EDIT: here is an example of what i'm trying to do:

    string P = "00F35DBCD6D4C296D2FE9118B659D02608B76FAC94BB58B10283F20390E2B259BAC602466162E9EF3E6A1590702CAE49B681A75A878E266F1AFAE0FA89DA5CA44A1551B517A3F80A9D6C630F9E7D239B437F7402DF8055069735894CD9D4708F8777B5E4F3E6A8B2D4EEE50DB2C96BA16D3C81FEB923697D649A8B7771B10E5B3F";
    string Q = "00B5AF039839043410E04C35BDDB30679969EBAC8B";
    string G = "00F300A68E54DE33A09001E28EC09F2ABF5DAF208774F2514D878D5587D870C91C6DE42B4705078C6F4438765050039C2950B6DE85AFC0D12A7A5C521782CB760918DF68F385A7F177DF50AA6BA0284090454106E422FCAE5390ADC00B859A433430019E970BFA614374DE1FB40C600345EF19DC01A122E4676C614DC29D3DC2FE";
    string Y = "00A5317849AF22BA6498F1EF973158C8BDA848BEB074CB141E629C927B18F29C8CE99815001BAAB2931F339B5C52A79BC3DCB0C5962C302707BA6FF1807EEB91D751BA723BB7512C20689AC5E67A1B656CDFD1BA2D4F6A44308509486AA8754B47784FC4C03E546897200388656BA5834A2CC0E18E58454FF60C1BA5411D6F50FD";

i'm missing the code for this intermediate piece. how do i convert P, Q, G, Y into the fingerprint. I tried different approaches, but i'm unsuccessful generating the fingerprint i see in the application that i'm trying to recreate.

        /* convert public key (bigIntKey) into fingerprint */
        var bigIntHash = new BigInteger(SHA1.Create().ComputeHash(key.ToByteArray()));
        byte[] hash = bigIntHash.ToByteArray();

        if (hash.Length != 20)
        {
            throw new IndexOutOfRangeException();
        }

        for (int i = 0; i < 5; i++)
        {
            int lf = BitConverter.ToInt32(hash, i * 4);
            Debug.Write(lf.ToString("X") + " ");
        }

EDIT2:

i tried this, but that is not working

        // switch P, Q, G, Y and separately to make it work.

        byte[] pArr = StringToByteArray(P);
        pArr = Tools.Endian.ReverseBytes(pArr);

        byte[] qArr = StringToByteArray(Q);
        qArr = Tools.Endian.ReverseBytes(qArr);

        byte[] gArr = StringToByteArray(G);
        gArr = Tools.Endian.ReverseBytes(gArr);

        byte[] yArr = StringToByteArray(Y);
        yArr = Tools.Endian.ReverseBytes(yArr);

        byte[] xArr = StringToByteArray(X);
        xArr = Tools.Endian.ReverseBytes(xArr);

        byte[] arr = Combine(pArr, qArr, gArr, yArr);

        DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();
        DSAParameters par = new DSAParameters();
        par.P = pArr;
        par.Q = qArr;
        par.G = gArr;
        par.Y = yArr;
        par.X = xArr;
        dsa.ImportParameters(par);
        var xml = dsa.ToXmlString(true);

It will fail on the ImportParameter.

Thank you

Was it helpful?

Solution

You need to follow the OTR spec, which says the components of the key use MPI encoding, which it specifies as the length (32 bit big-endian) followed by the integer (big-endian, no leading zeros)

void Main()
{
    string P = "00F35DBCD6D4C296D2FE9118B659D02608B76FAC94BB58B10283F20390E2B259BAC602466162E9EF3E6A1590702CAE49B681A75A878E266F1AFAE0FA89DA5CA44A1551B517A3F80A9D6C630F9E7D239B437F7402DF8055069735894CD9D4708F8777B5E4F3E6A8B2D4EEE50DB2C96BA16D3C81FEB923697D649A8B7771B10E5B3F";
    string Q = "00B5AF039839043410E04C35BDDB30679969EBAC8B";
    string G = "00F300A68E54DE33A09001E28EC09F2ABF5DAF208774F2514D878D5587D870C91C6DE42B4705078C6F4438765050039C2950B6DE85AFC0D12A7A5C521782CB760918DF68F385A7F177DF50AA6BA0284090454106E422FCAE5390ADC00B859A433430019E970BFA614374DE1FB40C600345EF19DC01A122E4676C614DC29D3DC2FE";
    string Y = "00A5317849AF22BA6498F1EF973158C8BDA848BEB074CB141E629C927B18F29C8CE99815001BAAB2931F339B5C52A79BC3DCB0C5962C302707BA6FF1807EEB91D751BA723BB7512C20689AC5E67A1B656CDFD1BA2D4F6A44308509486AA8754B47784FC4C03E546897200388656BA5834A2CC0E18E58454FF60C1BA5411D6F50FD";

    var publicKey = 
                ToMPI(HexToBytes(P))
        .Concat(ToMPI(HexToBytes(Q)))
        .Concat(ToMPI(HexToBytes(G)))
        .Concat(ToMPI(HexToBytes(Y)))
        .ToArray();

    var fingerprint=BitConverter.ToString(SHA1.Create().ComputeHash(publicKey)).Replace("-","");
    fingerprint.Dump();
}

byte[] ToMPI(byte[] data)
{
    //Truncate leading 0 bytes
    data = data.SkipWhile(b=>b==0).ToArray();

    //Length prefix - 32 bit big-endian integer
    var lenBytes=new byte[4];
    lenBytes[0]=(byte)(data.Length>>24);
    lenBytes[1]=(byte)(data.Length>>16);
    lenBytes[2]=(byte)(data.Length>>8);
    lenBytes[3]=(byte)(data.Length>>0);

    return lenBytes.Concat(data).ToArray();
}

// from http://stackoverflow.com/questions/311165/how-do-you-convert-byte-array-to-hexadecimal-string-and-vice-versa
public static byte[] HexToBytes(String hex)
{
  int NumberChars = hex.Length;
  byte[] bytes = new byte[NumberChars / 2];
  for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
  return bytes;
}

OTHER TIPS

MSDN mentions what you need to do your job on this page. Then, have a look at this answer from this SO page. The accepted answer gives the following code (and I quote):

var dsa = new DSACryptoServiceProvider();            
var privateKey = dsa.ExportParameters(true); // private key
var publicKey = dsa.ExportParameters(false); // public key

I think you have everything you need to get you going.

CHEERS!

I've used this class to generate a OTR DSA key: https://github.com/mohamedmansour/OTRLib/blob/master/Src/OTR/OTRUtilities/DSASigner.cs

Make the class public and call without constructor parameters.

var signer = new DSASigner();
var  _des_key_object = signer.GetDSAKeyParameters();

Later reuse of the same key:

string _dsa_key_1_p = _des_key_object.GetHexParamP();
string _dsa_key_1_q = _des_key_object.GetHexParamQ();
string _dsa_key_1_g = _des_key_object.GetHexParamG();
string _dsa_key_1_x = _des_key_object.GetHexParamX();

// This can be a JSON for storing.

var keysArray = new string[] { _dsa_key_1_p, _dsa_key_1_q, _dsa_key_1_g, _dsa_key_1_x };
_des_key_object = new DSAKeyParams(_des_key_objectJson[0], _des_key_objectJson[1], _des_key_objectJson[2], _des_key_objectJson[3]);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top