public void TestSignFlagJson() { Func <byte[], byte[]> sigFunc = (x) => { using (var rsa = new System.Security.Cryptography.RSACryptoServiceProvider()) { rsa.ImportParameters(JwsTests.GetRsaParamsForRfc7515Example_A_2_1()); using (var sha256 = new System.Security.Cryptography.SHA256CryptoServiceProvider()) { return(rsa.SignData(x, sha256)); } } }; object protectedSample = new // From the RFC example { alg = "RS256" }; object headerSample = new // From the RFC example { kid = "2010-12-29" }; string payloadSample = // From the RFC example "{\"iss\":\"joe\",\r\n" + " \"exp\":1300819380,\r\n" + " \"http://example.com/is_root\":true}"; var wsRegex = new Regex("\\s+"); var sigExpected = // Derived from the RFC example in A.6.4 wsRegex.Replace(@"{ ""header"":{""kid"":""2010-12-29""}, ""protected"":""eyJhbGciOiJSUzI1NiJ9"", ""payload"":""eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ"", ""signature"": ""cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"" }", ""); var sigActual = wsRegex.Replace(JwsHelper.SignFlatJson( sigFunc, payloadSample, protectedSample, headerSample), ""); Assert.AreEqual(sigExpected, sigActual); }
/// <summary> /// Computes the JWS-signed ACME request body for the given message object /// and signer instance. /// </summary> /// <param name="message"></param> /// <param name="signer"></param> /// <returns></returns> private string ComputeAcmeSigned(object message, ISigner signer) { var protectedHeader = new { nonce = NextNonce }; var unprotectedHeader = new { alg = Signer.JwsAlg, jwk = Signer.ExportJwk() }; var payload = string.Empty; if (message is JObject) { payload = ((JObject)message).ToString(Formatting.None); } else { payload = JsonConvert.SerializeObject(message, Formatting.None); } var acmeSigned = JwsHelper.SignFlatJson(Signer.Sign, payload, protectedHeader, unprotectedHeader); return(acmeSigned); }
[Ignore] // *Normally*, we skip this test because it depends on a local Boulder setup to accessible public void TestNewRegRequest() { var requ = WebRequest.Create(_rootUrl); var resp = requ.GetResponse(); Assert.IsNotNull(resp); var nonceKey = resp.Headers.AllKeys.FirstOrDefault( x => x.Equals("Replay-nonce", StringComparison.OrdinalIgnoreCase)); Assert.IsFalse(string.IsNullOrEmpty(nonceKey)); var nonceValue = resp.Headers[nonceKey]; var newReg = new { resource = "new-reg", contact = new string[] { "mailto:[email protected]", // Tel contact method is no longer supported by Boulder //"tel:+12025551212" }, }; var newRegSer = JsonConvert.SerializeObject(newReg); var algSigner = new RS256Signer(); algSigner.Init(); var unprotectedHeader = new { alg = "RS256", jwk = algSigner.ExportJwk() }; var protectedHeader = new { nonce = nonceValue, }; var acmeJson = JwsHelper.SignFlatJson(algSigner.Sign, newRegSer, protectedHeader, unprotectedHeader); var acmeJsonBytes = Encoding.ASCII.GetBytes(acmeJson); requ = WebRequest.Create(new Uri(_rootUrl, "/acme/new-reg")); requ.Method = "POST"; requ.ContentType = "application/json"; requ.ContentLength = acmeJsonBytes.Length; using (var s = requ.GetRequestStream()) { s.Write(acmeJsonBytes, 0, acmeJsonBytes.Length); } resp = requ.GetResponse(); }