public static EncryptionResult Encrypt(byte[] userKey, byte[] userSecret, byte[] payload) { byte[] salt = GenerateSalt(16); AsymmetricCipherKeyPair serverKeyPair = ECKeyHelper.GenerateKeys(); IBasicAgreement ecdhAgreement = AgreementUtilities.GetBasicAgreement("ECDH"); ecdhAgreement.Init(serverKeyPair.Private); ECPublicKeyParameters userPublicKey = ECKeyHelper.GetPublicKey(userKey); byte[] key = ecdhAgreement.CalculateAgreement(userPublicKey).ToByteArrayUnsigned(); byte[] serverPublicKey = ((ECPublicKeyParameters)serverKeyPair.Public).Q.GetEncoded(false); byte[] prk = HKDF(userSecret, key, Encoding.UTF8.GetBytes("Content-Encoding: auth\0"), 32); byte[] cek = HKDF(salt, prk, CreateInfoChunk("aesgcm", userKey, serverPublicKey), 16); byte[] nonce = HKDF(salt, prk, CreateInfoChunk("nonce", userKey, serverPublicKey), 12); byte[] input = AddPaddingToInput(payload); byte[] encryptedMessage = EncryptAes(nonce, cek, input); return(new EncryptionResult { Salt = salt, Payload = encryptedMessage, PublicKey = serverPublicKey }); }
public void TestGetPublicKey() { var publicKey = UrlBase64.Decode(TestPublicKey); var publicKeyParams = ECKeyHelper.GetPublicKey(publicKey); var importedPublicKey = UrlBase64.Encode(publicKeyParams.Q.GetEncoded(false)); Assert.Equal(TestPublicKey, importedPublicKey); }
public void TestGetPrivateKey() { var privateKey = UrlBase64.Decode(TestPrivateKey); var privateKeyParams = ECKeyHelper.GetPrivateKey(privateKey); var importedPrivateKey = UrlBase64.Encode(privateKeyParams.D.ToByteArrayUnsigned()); Assert.Equal(TestPrivateKey, importedPrivateKey); }
public void TestGetPrivateKey() { byte[] privateKey = UrlBase64.Decode(TEST_PRIVATE_KEY); ECPrivateKeyParameters privateKeyParams = ECKeyHelper.GetPrivateKey(privateKey); string importedPrivateKey = UrlBase64.Encode(privateKeyParams.D.ToByteArrayUnsigned()); Assert.AreEqual(TEST_PRIVATE_KEY, importedPrivateKey); }
public void TestGetPublicKey() { byte[] publicKey = UrlBase64.Decode(TEST_PUBLIC_KEY); ECPublicKeyParameters publicKeyParams = ECKeyHelper.GetPublicKey(publicKey); string importedPublicKey = UrlBase64.Encode(publicKeyParams.Q.GetEncoded(false)); Assert.AreEqual(TEST_PUBLIC_KEY, importedPublicKey); }
/// <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); }
public void TestGenerateKeys() { var keys = ECKeyHelper.GenerateKeys(); var publicKey = ((ECPublicKeyParameters)keys.Public).Q.GetEncoded(false); var privateKey = ((ECPrivateKeyParameters)keys.Private).D.ToByteArrayUnsigned(); var publicKeyLength = publicKey.Length; var privateKeyLength = privateKey.Length; Assert.Equal(65, publicKeyLength); Assert.Equal(32, privateKeyLength); }
/// <summary> /// Generate vapid keys /// </summary> /// <returns></returns> public static VapidDetails GenerateVapidKeys() { VapidDetails results = new VapidDetails(); AsymmetricCipherKeyPair keys = ECKeyHelper.GenerateKeys(); byte[] publicKey = ((ECPublicKeyParameters)keys.Public).Q.GetEncoded(false); byte[] privateKey = ((ECPrivateKeyParameters)keys.Private).D.ToByteArrayUnsigned(); results.PublicKey = UrlBase64.Encode(publicKey); results.PrivateKey = UrlBase64.Encode(privateKey); return(results); }
public void TestGenerateKeysNoCache() { var keys1 = ECKeyHelper.GenerateKeys(); var keys2 = ECKeyHelper.GenerateKeys(); var publicKey1 = ((ECPublicKeyParameters)keys1.Public).Q.GetEncoded(false); var privateKey1 = ((ECPrivateKeyParameters)keys1.Private).D.ToByteArrayUnsigned(); var publicKey2 = ((ECPublicKeyParameters)keys2.Public).Q.GetEncoded(false); var privateKey2 = ((ECPrivateKeyParameters)keys2.Private).D.ToByteArrayUnsigned(); Assert.False(publicKey1.SequenceEqual(publicKey2)); Assert.False(privateKey1.SequenceEqual(privateKey2)); }
public void TestGenerateKeys() { AsymmetricCipherKeyPair keys = ECKeyHelper.GenerateKeys(); byte[] publicKey = ((ECPublicKeyParameters)keys.Public).Q.GetEncoded(false); byte[] privateKey = ((ECPrivateKeyParameters)keys.Private).D.ToByteArrayUnsigned(); int publicKeyLength = publicKey.Length; int privateKeyLength = privateKey.Length; Assert.AreEqual(65, publicKeyLength); Assert.AreEqual(32, privateKeyLength); ; }
private static byte[] GetKeyingMaterial(PushSubscription subscription, AsymmetricKeyParameter applicationServerPrivateKey, byte[] applicationServerPublicKey) { IBasicAgreement ecdhAgreement = AgreementUtilities.GetBasicAgreement("ECDH"); ecdhAgreement.Init(applicationServerPrivateKey); byte[] userAgentPublicKey = UrlBase64Converter.FromUrlBase64String(subscription.GetKey(PushEncryptionKeyName.P256DH)); byte[] authenticationSecret = UrlBase64Converter.FromUrlBase64String(subscription.GetKey(PushEncryptionKeyName.Auth)); byte[] sharedSecret = ecdhAgreement.CalculateAgreement(ECKeyHelper.GetECPublicKeyParameters(userAgentPublicKey)).ToByteArrayUnsigned(); byte[] sharedSecretHash = HmacSha256(authenticationSecret, sharedSecret); byte[] infoParameter = GetKeyingMaterialInfoParameter(userAgentPublicKey, applicationServerPublicKey); byte[] keyingMaterial = HmacSha256(sharedSecretHash, infoParameter); return(keyingMaterial); }
/// <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> { { "typ", "JWT" }, { "alg", "ES256" } }; var jwtPayload = new Dictionary <string, object> { { "aud", audience }, { "exp", expiration }, { "sub", subject } }; var signingKey = ECKeyHelper.GetPrivateKey(decodedPrivateKey); var signer = new JWSSigner(signingKey); var token = signer.GenerateSignature(header, jwtPayload); var results = new Dictionary <string, string> { { "Authorization", "WebPush " + token }, { "Crypto-Key", "p256ecdsa=" + publicKey } }; return(results); }
private static HttpRequestMessage SetContent(HttpRequestMessage pushMessageDeliveryRequest, PushSubscription subscription, PushMessage message) { if (message.HttpContent is null) { pushMessageDeliveryRequest.Content = null; } else { AsymmetricCipherKeyPair applicationServerKeys = ECKeyHelper.GenerateAsymmetricCipherKeyPair(); byte[] applicationServerPublicKey = ((ECPublicKeyParameters)applicationServerKeys.Public).Q.GetEncoded(false); pushMessageDeliveryRequest.Content = new Aes128GcmEncodedContent( message.HttpContent, GetKeyingMaterial(subscription, applicationServerKeys.Private, applicationServerPublicKey), applicationServerPublicKey, CONTENT_RECORD_SIZE ); } return(pushMessageDeliveryRequest); }
public void TestGenerateSignature() { var decodedPrivateKey = UrlBase64.Decode(TestPrivateKey); var privateKey = ECKeyHelper.GetPrivateKey(decodedPrivateKey); var header = new Dictionary <string, object>(); header.Add("typ", "JWT"); header.Add("alg", "ES256"); var jwtPayload = new Dictionary <string, object>(); jwtPayload.Add("aud", "aud"); jwtPayload.Add("exp", 1); jwtPayload.Add("sub", "subject"); var signer = new JwsSigner(privateKey); var token = signer.GenerateSignature(header, jwtPayload); var tokenParts = token.Split('.'); Assert.AreEqual(3, tokenParts.Length); var encodedHeader = tokenParts[0]; var encodedPayload = tokenParts[1]; var signature = tokenParts[2]; var decodedHeader = Encoding.UTF8.GetString(UrlBase64.Decode(encodedHeader)); var decodedPayload = Encoding.UTF8.GetString(UrlBase64.Decode(encodedPayload)); Assert.AreEqual(@"{""typ"":""JWT"",""alg"":""ES256""}", decodedHeader); Assert.AreEqual(@"{""aud"":""aud"",""exp"":1,""sub"":""subject""}", decodedPayload); var decodedSignature = UrlBase64.Decode(signature); var decodedSignatureLength = decodedSignature.Length; var isSignatureLengthValid = decodedSignatureLength == 66 || decodedSignatureLength == 64; Assert.AreEqual(true, isSignatureLengthValid); }
public void TestGenerateSignature() { ECPrivateKeyParameters privateKey = ECKeyHelper.GetPrivateKey(new byte[32]); Dictionary <string, object> header = new Dictionary <string, object>(); header.Add("typ", "JWT"); header.Add("alg", "ES256"); Dictionary <string, object> jwtPayload = new Dictionary <string, object>(); jwtPayload.Add("aud", "aud"); jwtPayload.Add("exp", 1); jwtPayload.Add("sub", "subject"); JWSSigner signer = new JWSSigner(privateKey); string token = signer.GenerateSignature(header, jwtPayload); string[] tokenParts = token.Split('.'); Assert.AreEqual(3, tokenParts.Length); string encodedHeader = tokenParts[0]; string encodedPayload = tokenParts[1]; string signature = tokenParts[2]; string decodedHeader = Encoding.UTF8.GetString(UrlBase64.Decode(encodedHeader)); string decodedPayload = Encoding.UTF8.GetString(UrlBase64.Decode(encodedPayload)); Assert.AreEqual(@"{""typ"":""JWT"",""alg"":""ES256""}", decodedHeader); Assert.AreEqual(@"{""aud"":""aud"",""exp"":1,""sub"":""subject""}", decodedPayload); byte[] decodedSignature = UrlBase64.Decode(signature); int decodedSignatureLength = decodedSignature.Length; bool isSignatureLengthValid = decodedSignatureLength == 66 || decodedSignatureLength == 64; Assert.AreEqual(true, isSignatureLengthValid); }
/// <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); byte[] decodedPrivateKey = UrlBase64.Decode(privateKey); if (expiration == -1) { expiration = UnixTimeNow() + 43200; } Dictionary <string, object> header = new Dictionary <string, object>(); header.Add("typ", "JWT"); header.Add("alg", "ES256"); Dictionary <string, object> jwtPayload = new Dictionary <string, object>(); jwtPayload.Add("aud", audience); jwtPayload.Add("exp", expiration); jwtPayload.Add("sub", subject); ECPrivateKeyParameters signingKey = ECKeyHelper.GetPrivateKey(decodedPrivateKey); JWSSigner signer = new JWSSigner(signingKey); string token = signer.GenerateSignature(header, jwtPayload); Dictionary <string, string> results = new Dictionary <string, string>(); results.Add("Authorization", "WebPush " + token); results.Add("Crypto-Key", "p256ecdsa=" + publicKey); return(results); }