Skip to content

Instantly share code, notes, and snippets.

@ezekg
Last active June 14, 2021 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ezekg/f39b357d546dae3e90fba6635db35af5 to your computer and use it in GitHub Desktop.
Save ezekg/f39b357d546dae3e90fba6635db35af5 to your computer and use it in GitHub Desktop.
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Security;
using System.Text;
using System;
class Program
{
const string KEYGEN_ACTIVATION_PROOF = "proof/eyJhY2NvdW50Ijp7ImlkIjoiYjEyMmRmN2MtN2UzNi00NjNiLTlhYzMtYzkzZmYzOGIzMTFmIn0sInByb2R1Y3QiOnsiaWQiOiJiZWZlMjBjMS05MTE4LTQ2MmMtYWFhNS0yMWE2MmUxNmU5NWEifSwicG9saWN5Ijp7ImlkIjoiYTg2YWU0NmUtMTQzMS00ZDVjLWJkNzUtN2YzODNlZDY4YjA2IiwiZHVyYXRpb24iOjg2NDAwfSwibGljZW5zZSI6eyJpZCI6IjI2MzhiZWFmLTIwMWMtNDg5ZS1iODA2LTRhOWEwN2ZhYzA4OSIsImtleSI6ImtleS9ORlJMUmkwMFYxWlNMVlZHTkZndE4xZElTQzFOVkZsTUxWWktXRTR0TjAwelJpMVFVbGRTLm5UMXBENFA2OUFnVTNVa0x3eFlLU19RNU03RHV3ekZtZ0pDOWd2N1ZGUmNiWkxJYUZsSVktY2hMbnEtUTNNUVk1dlUydURobHNXUkhfQnBHRkVITDZxcFIzQ1otX2lVYmdoU2pBM1FiNl80RVVhcjBTMlhsd2d2ZHUyVFJHTGRkRG52cTBaOGEtak1vRmpnc1RVVzZqZG5yR1NBQUNFQkNHX0I0QkVQWTN2MEVBeE5GUTJRU1RwUE1jbFhhTGlKWlZIa0NSSGhQdWI5T0NmN0JTWTVUWWhFLVoxeGVrQ29teXppQlFlWEpVMjJ6MnJqZHVhMEk4WUNvdWJkbkNoUDNtdjI3SWxsQUREaHZpYW1oSHAxNnB5dFdCNk1tdWxfY19KMFh5Skk4UE85bndHdTFoS2tkYVJVZjdvdXVhQm5VM0Vxams4aEw1SkxVUEw1OElLZkxOZz09IiwiZXhwaXJ5IjoiMjAyMS0wNi0xMVQwMDowMDowMC4wMDBaIn0sIm1hY2hpbmUiOnsiaWQiOiI4ODg5ZTc0Yy1lNTM2LTQ5ODUtOGEwMi03ZDU3YmY4Yzg3NGMiLCJmaW5nZXJwcmludCI6IkRvbmFsZFR1cm5lci1XYXMtSGVyZS1BQjpDRkciLCJjcmVhdGVkIjoiMjAyMS0wNi0wOVQyMzo1MTo0NC41NzVaIn0sInRzIjoiMjAyMS0wNi0xMFQxNjo1MjoyOS40MDFaIn0=.U8FwFmcCi_VwbeyPdwW9sH89ehzJhtaRausfNMWof7Q4g5IqysJ2FsrZl6DG5DR50MxI5W69pO9yxmOeaZ_FYZolXTPJtEchjPzB_m9kHh98VdJbuQlu5kwN_bhwL1tgSjyXlirfsAfrWVoqmzmdqpWVaVixkQRzCSflD60icHfQVXsAd2j8LTLcAoufDHwu0iy3Pod-I8oeBSOeK3xjs83BDUQvwSEJtg3wV8YV9ep7htVeqfCLgGijqHZjGW-Im-BP-5yty28OOtp5ad8TJ1s1OtF3HEyu-VWKrI4fTy1btF0OByJbFiz0qAoyOVR6q6GeRshce7iMARomeGS0dg==";
const string KEYGEN_PUBLIC_KEY = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFyR25RbDhqV3hTcHhkaW9scHhFTQpIU3I2akFhV2Y2NGxvUzNrenBBRGVLWUUwN28rN0I2N2JsNksxbUJqWFNzRzN3eVJJb1dUcEVROFg0RkxydWJqCjNXUC92RXQ5S1FVR1ovbit3azlXaTl2NkQzOXZLS28xWUNEQjVmMlVYOEFTbzB2RGlHQU1NQisvYmwrRHdqR0IKeVpES3BmMDhzcUxJc1RjT3hlUEVWcXNTdlh3cmtIK3czalR5MVlIcTY5MFhrUWVETjBDY3BDNWJEdlFReWF2aAo3anpZVHJzUzNCUjZIN0pPSm1tMFk2ZGh1N2xBQlZQVGpVOTVkaENBQUhUL1FjUHliU3RDMGVrekh0OXFkNFREClMyK2ZoQXJNeWI4ejlEdjdhaFh1eUJxdVMxdnBvUmFJZHZCZTVPWGJTcmt5Z0IzNi93bS9BOWNlK2pCck9qdkUKRHdJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==";
public static void Main (string[] args)
{
var pemPublicKey = Encoding.UTF8.GetString(
Convert.FromBase64String(KEYGEN_PUBLIC_KEY)
);
// Parse and convert the base64 PEM public key to ASN1 format
var encodedAns1PublicKey = pemPublicKey
.Replace("-----BEGIN PUBLIC KEY-----", string.Empty)
.Replace("-----END PUBLIC KEY-----", string.Empty)
.Trim();
var asn1PublicKey = Convert.FromBase64String(encodedAns1PublicKey);
// Import the public key
var publicKey = PublicKeyFactory.CreateKey(asn1PublicKey);
// Initialize RSA
var digest = new Sha256Digest();
var engine = new RsaEngine();
var rsa = new RsaDigestSigner(digest);
rsa.Init(false, publicKey);
// Parse the activation proof
var activationProof = KEYGEN_ACTIVATION_PROOF;
var proofParts = activationProof.Split('.');
var signingData = proofParts[0];
var encodedSignature = ConvertBase64UrlString(proofParts[1]);
var dataParts = signingData.Split('/');
var signingPrefix = dataParts[0];
var encodedData = ConvertBase64UrlString(dataParts[1]);
if (signingPrefix != "proof")
{
Console.WriteLine("[ERROR] Invalid activation proof prefix: prefix={0}", signingPrefix);
Environment.Exit(1);
}
// Convert data to bytes for verification
var signingDataBytes = Encoding.UTF8.GetBytes($"proof/{encodedData}");
var signatureBytes = Convert.FromBase64String(encodedSignature);
// Verify the activation proof's signature
rsa.BlockUpdate(signingDataBytes, 0, signingDataBytes.Length);
var ok = rsa.VerifySignature(signatureBytes);
if (ok)
{
var decodedDataBytes = Convert.FromBase64String(encodedData);
var decodedData = Encoding.UTF8.GetString(decodedDataBytes);
Console.WriteLine("[INFO] Activation proof is cryptographically valid: proof={0} dataset={1}", activationProof, decodedData);
Environment.Exit(0);
}
else
{
Console.WriteLine("[ERROR] Activation proof is not valid: proof={0}", activationProof);
Environment.Exit(1);
}
}
// Cryptographic keys use base64url encoding: https://keygen.sh/docs/api/#license-signatures
private static string ConvertBase64UrlString(string s)
{
return s.Replace("-", "+").Replace("_", "/");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment