cscの作法 その282


# 概要
cscの作法、調べてみた。
jwtを検証してみた。

# 検証したjwt

- 出所

wikiペディア

- 全体

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9.gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI

```

- タイプ

HS256

- キー

secretkey

- ヘッダー

{
    "alg": "HS256",
    "typ": "JWT"
}

- ペイロード

{
    "loggedInAs":"admin",
    "iat":1422779638
}

- シグニチャー

gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI

# 結果

```


{"alg":"HS256","typ":"JWT"}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
{"alg":"HS256","typ":"JWT"}
{"loggedInAs":"admin","iat":1422779638}
eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9
eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9
{"loggedInAs":"admin","iat":1422779638}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsb2dnZWRJbkFzIjoiYWRtaW4iLCJpYXQiOjE0MjI3Nzk2Mzh9
secretkey
HS256
gzSraSYS8EXBxLN/oWnFSRgCzcmJmMjLiuyu5CSpyHI=
gzSraSYS8EXBxLN_oWnFSRgCzcmJmMjLiuyu5CSpyHI


```

# サンプルコード

```
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using LitJson;

public enum JwtHashAlgorithm {
	RS256,
	HS384,
	HS512,
	HS256
}
public class jwt {
	static jwt() {
		HashAlgorithms = new Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> {{
			JwtHashAlgorithm.RS256, (key, value) => {
				using (var sha = new HMACSHA256(key))
				{
					return sha.ComputeHash(value);
				}
			}
		}, {
			JwtHashAlgorithm.HS384, (key, value) => {
				using (var sha = new HMACSHA384(key))
				{
					return sha.ComputeHash(value);
				}
			}
		}, {
			JwtHashAlgorithm.HS512, (key, value) => {
				using (var sha = new HMACSHA512(key))
				{
					return sha.ComputeHash(value);
				}
			}
		}, {
			JwtHashAlgorithm.HS256, (key, value) => {
				using (var sha = new HMACSHA256(key))
				{
					return sha.ComputeHash(value);
				}
			}
		}};
	}
	public static Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> HashAlgorithms;
	public static JwtHashAlgorithm GetHashAlgorithm(string algorithm) {
		switch (algorithm)
		{
		case "RS256":
			return JwtHashAlgorithm.RS256;
		case "HS384":
			return JwtHashAlgorithm.HS384;
		case "HS512":
			return JwtHashAlgorithm.HS512;
		case "HS256":
			return JwtHashAlgorithm.HS256;
		default:
			throw new InvalidOperationException("Algorithm not supported.");
		}
	}
	public static string Decode(string token, string key) {
		return Decode(token, key, true);
	}
	public static string Decode(string token, string key, bool verify) {
		var parts = token.Split('.');
		var header = parts[0];
		var payload = parts[1];
		byte[] crypto = Base64UrlDecode(parts[2]);
		var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
		var headerData = LitJson.JsonMapper.ToObject(headerJson);
		var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
		var payloadData = LitJson.JsonMapper.ToObject(payloadJson);
		if (verify)
		{
			var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
			var keyBytes = Encoding.UTF8.GetBytes(key);
			var algorithm = (string) headerData["alg"];
			var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
			var decodedCrypto = Convert.ToBase64String(crypto);
			var decodedSignature = Convert.ToBase64String(signature);
			if (decodedCrypto != decodedSignature)
			{
				throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
			}
		}
		return payloadData.ToString();
	}
	public static string Encode(object payload, string key, JwtHashAlgorithm algorithm) {
		return Encode(payload, Encoding.UTF8.GetBytes(key), algorithm);
	}
	public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm) {
		var segments = new List<string>();
		var header = new {
			alg = algorithm.ToString(),
			typ = "JWT"
		};
		byte[] headerBytes = Encoding.UTF8.GetBytes(LitJson.JsonMapper.ToJson(header));
		byte[] payloadBytes = Encoding.UTF8.GetBytes(LitJson.JsonMapper.ToJson(payload));
		segments.Add(Base64UrlEncode(headerBytes));
		segments.Add(Base64UrlEncode(payloadBytes));
		var stringToSign = string.Join(".", segments.ToArray());
		var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);
		byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign);
		segments.Add(Base64UrlEncode(signature));
		return string.Join(".", segments.ToArray());
	}
	public static string Base64UrlEncode(byte[] input) {
		var output = Convert.ToBase64String(input);
		output = output.Split('=')[0];
		output = output.Replace('+', '-');
		output = output.Replace('/', '_');
		return output;
	}
	public static byte[] Base64UrlDecode(string input) {
		var output = input;
		output = output.Replace('-', '+');
		output = output.Replace('_', '/');
		switch (output.Length % 4)
		{
		case 0:
		break;
		case 2:
			output += "==";
		break;
		case 3:
			output += "=";
		break;
		default:
			throw new System.Exception("Illegal base64url string!");
		}
		var converted = Convert.FromBase64String(output);
		return converted;
	}
}

public class test0 {
	static void Main() {
		var header = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
		Console.WriteLine(header);
		byte[] headerBytes = Encoding.UTF8.GetBytes(header);
		var po0 = jwt.Base64UrlEncode(headerBytes);
		Console.WriteLine(po0);
		Console.WriteLine("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9");
		var p0 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
		byte[] hed = jwt.Base64UrlDecode(p0);
		var heds = Encoding.UTF8.GetString(hed);
		Console.WriteLine(heds);

		var payload = "{\"sub\":\"1234567890\",\"iat\":1516239022}";
		Console.WriteLine(payload);
		byte[] payBytes = Encoding.UTF8.GetBytes(payload);
		var po1 = jwt.Base64UrlEncode(payBytes);
		Console.WriteLine(po1);
		Console.WriteLine("eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ");
		var p1 = "eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ";
		byte[] pay = jwt.Base64UrlDecode(p1);
		var pays = Encoding.UTF8.GetString(pay);
		Console.WriteLine(pays);

		var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(po0, ".", po1));
		Console.WriteLine(Encoding.UTF8.GetString(bytesToSign));
		var keyBytes = Encoding.UTF8.GetBytes("secret");
		Console.WriteLine(Encoding.UTF8.GetString(keyBytes));
		var algorithm = "HS256";
		Console.WriteLine(jwt.GetHashAlgorithm(algorithm));
		var signature = jwt.HashAlgorithms[jwt.GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
		var decodedSignature = Convert.ToBase64String(signature);
		Console.WriteLine(decodedSignature);
		Console.WriteLine("t42p4AHef69Tyyi88U6+p0utZYYrg7mmCGhoAd7Zffs");

	}
}





```


以上。