public static EncryptionResult Encrypt(byte[] userKey, byte[] userSecret, byte[] payload) { var salt = GenerateSalt(16); var serverKeyPair = ECKeyHelper.GenerateKeys(); var ecdhAgreement = AgreementUtilities.GetBasicAgreement("ECDH"); ecdhAgreement.Init(serverKeyPair.Private); var userPublicKey = ECKeyHelper.GetPublicKey(userKey); var key = ecdhAgreement.CalculateAgreement(userPublicKey).ToByteArrayUnsigned(); var serverPublicKey = ((ECPublicKeyParameters)serverKeyPair.Public).Q.GetEncoded(false); var prk = HKDF(userSecret, key, Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32); var cek = HKDF(salt, prk, CreateInfoChunk("aesgcm", userKey, serverPublicKey), 16); var nonce = HKDF(salt, prk, CreateInfoChunk("nonce", userKey, serverPublicKey), 12); var input = AddPaddingToInput(payload); var encryptedMessage = EncryptAes(nonce, cek, input); return(new EncryptionResult { Salt = salt, Payload = encryptedMessage, PublicKey = serverPublicKey }); }
/// <summary> /// Generate vapid keys /// </summary> public static VapidDetails GenerateVapidKeys() { var results = new VapidDetails(); var keys = ECKeyHelper.GenerateKeys(); var publicKey = ((ECPublicKeyParameters)keys.Public).Q.GetEncoded(false); var privateKey = ((ECPrivateKeyParameters)keys.Private).D.ToByteArrayUnsigned(); results.PublicKey = UrlBase64.Encode(publicKey); results.PrivateKey = UrlBase64.Encode(ByteArrayPadLeft(privateKey, 32)); return(results); }
/// <summary> /// This method takes the required VAPID parameters and returns the required /// header to be added to a Web Push Protocol Request. /// </summary> /// <param name="audience">This must be the origin of the push service.</param> /// <param name="subject">This should be a URL or a 'mailto:' email address</param> /// <param name="publicKey">The VAPID public key as a base64 encoded string</param> /// <param name="privateKey">The VAPID private key as a base64 encoded string</param> /// <param name="expiration">The expiration of the VAPID JWT.</param> /// <returns>A dictionary of header key/value pairs.</returns> public static Dictionary <string, string> GetVapidHeaders(string audience, string subject, string publicKey, string privateKey, long expiration = -1) { ValidateAudience(audience); ValidateSubject(subject); ValidatePublicKey(publicKey); ValidatePrivateKey(privateKey); var decodedPrivateKey = UrlBase64.Decode(privateKey); if (expiration == -1) { expiration = UnixTimeNow() + 43200; } var header = new Dictionary <string, object>(); header.Add("typ", "JWT"); header.Add("alg", "ES256"); var jwtPayload = new Dictionary <string, object>(); jwtPayload.Add("aud", audience); jwtPayload.Add("exp", expiration); jwtPayload.Add("sub", subject); var signingKey = ECKeyHelper.GetPrivateKey(decodedPrivateKey); var signer = new JWSSigner(signingKey); var token = signer.GenerateSignature(header, jwtPayload); var results = new Dictionary <string, string>(); results.Add("Authorization", "WebPush " + token); results.Add("Crypto-Key", "p256ecdsa=" + publicKey); return(results); }