/// <summary> /// Encode a ProxyToken to base64 JWT, and sign it with the private key /// provided by the certificate. /// </summary> /// <param name="payload"> /// The ProxyToken to be encoded. /// </param> /// <param name="signingCertificate"> /// The X509Certificate which includes the private key to sign the JWT. /// </param> /// <returns> /// The base64 encoded JWT with signature appended. /// </returns> public static string Encode(ProxyToken payload, X509Certificate2 signingCertificate) { // header, payload and signature are joint by dot // header.payload.signature var segments = new List <string>(); // RS256 is the ONLY algorithm that works var header = new JwtHeader { typ = Type, alg = SigningAlgorithm }; // x5t is the base64 encoded SHA1 hash of the certificate // must use SHA1 hash algorithm here header.x5t = Base64Helper.Base64Encode(signingCertificate.GetCertHash()); // header and payload should be encoded using UTF8 var base64header = Base64Helper.Base64Encode(Encoding.UTF8.GetBytes(header.ToString())); var base64payload = Base64Helper.Base64Encode(Encoding.UTF8.GetBytes(payload.ToString())); segments.Add(base64header); segments.Add(base64payload); // what we sign is the base64 encoded result var stringToSign = string.Join(".", segments.ToArray()); // sign the data: header and payload var signature = RSASigningHelper.SignData( // data to be signed should use ASCII encoding Encoding.ASCII.GetBytes(stringToSign), signingCertificate, HashAlgorithm); segments.Add(Base64Helper.Base64Encode(signature)); return(string.Join(".", segments.ToArray())); }
/// <summary> /// Decodes the base64 JWT and veries it with the public key /// in the certificate provided. /// </summary> /// <param name="token"> /// The base64-encoded JWT. /// </param> /// <param name="signingCertificate"> /// The certificate with the public key to verify the JWT. /// </param> /// <param name="verity"> /// If this value is true, signature verification will be proceeded. /// </param> /// <returns> /// The decoded ProxyToken. /// </returns> public static ProxyToken Decode(string token, X509Certificate2 signingCertificate, bool verity = false) { var segments = token.Split('.'); if (verity) { // get the signed data by decoding the string with ASCII // because when signing it, we use ASCII var signedData = Encoding.ASCII.GetBytes(string.Concat(segments[0], ".", segments[1])); var signature = Base64Helper.Base64Decode(segments[2]); // veify the signature if (!RSASigningHelper.VerifySignature(signedData, signature, signingCertificate, HashAlgorithm)) { throw new CryptographicException("Invalid signature"); } } // decode header and payload var header = Encoding.UTF8.GetString(Base64Helper.Base64Decode(segments[0])); var payload = Encoding.UTF8.GetString(Base64Helper.Base64Decode(segments[1])); return(JSONObject.Parse <ProxyToken>(payload)); }