I have written two programs which will exchange X25519 public keys and then calculate shared secret. This is just a test, so public keys are exchanged trough text files (in PEM format), program is until you tell it to continue in order to generate keypairs and exchange them.
First one is in Dart:
import 'dart:convert';
import 'dart:io';
import 'package:cryptography/cryptography.dart';
import 'package:pem/pem.dart';
Future<void> main(List<String> arguments) async {
//https://pub.dev/documentation/cryptography/latest/cryptography/X25519-class.html
final algorithm = Cryptography.instance.x25519();
final keyPair = await algorithm.newKeyPair();
var file = File('/home/razj/dartPublic.txt');
file.writeAsStringSync(PemCodec(PemLabel.publicKey)
.encode(await keyPair.extractPublicKeyBytes()));
print('PRESS AFTER C# PROGRAM GENERATES KEYPAIR');
stdin.readLineSync();
String remotePem = File('/home/razj/sharpPublic.txt').readAsStringSync();
SimplePublicKey remotePublicKey = SimplePublicKey(
PemCodec(PemLabel.publicKey).decode(remotePem),
type: KeyPairType.x25519);
final sharedSecretKey = await algorithm.sharedSecretKey(
keyPair: keyPair,
remotePublicKey: remotePublicKey,
);
List<int> sharedKeyBytes = await sharedSecretKey.extractBytes();
print(base64.encode(sharedKeyBytes));
}
extension SimpleKeyPairExtension on SimpleKeyPair {
Future<List<int>> extractPublicKeyBytes() {
return extract().then((value) => value.bytes);
}
}
Second is in .NET CORE:
using System.Security.Cryptography;
using X25519;
internal class Program
{
private static void Main(string[] args)
{
//https://github.com/HirbodBehnam/X25519-CSharp
var keyPair = X25519KeyAgreement.GenerateKeyPair();
File.WriteAllText("/home/razj/sharpPublic.txt", new string(PemEncoding.Write("PUBLIC KEY", keyPair.PublicKey)));
Console.WriteLine("PRESS AFTER DART PROGRAM GENERATES KEYPAIR");
Console.ReadKey(true);
string remotePem = File.ReadAllText("/home/razj/dartPublic.txt").Replace("-----BEGIN PUBLIC KEY-----\n", "").Replace("\n-----END PUBLIC KEY-----\n", "");
byte[] sharedKeyBytes = X25519KeyAgreement.Agreement(keyPair.PrivateKey, Convert.FromBase64String(remotePem));
Console.WriteLine(Convert.ToBase64String(sharedKeyBytes));
}
}
In the end of each program I print base64 encoded byte array which represents the shared key. Unfortunately outputs doesn't match. Any idea how to fix this or what might be wrong? Thanks for answering.
As @Topaco said,
Just exchanged keys by encoding raw key bytes to Base64 string:
Dart:
.NET CORE
Dart output:
.NET-CORE output