Files
pages/2019/11/21/enc.html
2025-12-31 16:00:29 +00:00

361 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Web Crypto Api学习笔记 | Mayx的博客</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="Web Crypto Api学习笔记" />
<meta name="author" content="mayx" />
<meta property="og:locale" content="zh_CN" />
<meta name="description" content="感觉要爆炸了……" />
<meta property="og:description" content="感觉要爆炸了……" />
<meta property="og:site_name" content="Mayx的博客" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-11-21T00:00:00+08:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="Web Crypto Api学习笔记" />
<meta name="google-site-verification" content="huTYdEesm8NaFymixMNqflyCp6Jfvd615j5Wq1i2PHc" />
<meta name="msvalidate.01" content="0ADFCE64B3557DC4DC5F2DC224C5FDDD" />
<meta name="yandex-verification" content="fc0e535abed800be" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"mayx"},"dateModified":"2019-11-21T00:00:00+08:00","datePublished":"2019-11-21T00:00:00+08:00","description":"感觉要爆炸了……","headline":"Web Crypto Api学习笔记","mainEntityOfPage":{"@type":"WebPage","@id":"/2019/11/21/enc.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://avatars0.githubusercontent.com/u/17966333"},"name":"mayx"},"url":"/2019/11/21/enc.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="canonical" href="https://mabbs.github.io/2019/11/21/enc.html" />
<link type="application/atom+xml" rel="alternate" href="/atom.xml" title="Mayx的博客" />
<link rel="alternate" type="application/rss+xml" title="Mayx的博客(RSS)" href="/rss.xml" />
<link rel="alternate" type="application/json" title="Mayx的博客(JSON Feed)" href="/feed.json" />
<link rel="stylesheet" href="/assets/css/style.css?v=1767196818" />
<!--[if !IE]> -->
<link rel="stylesheet" href="/Live2dHistoire/live2d/css/live2d.css" />
<!-- <![endif]-->
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Mayx的博客" />
<link rel="webmention" href="https://webmention.io/mabbs.github.io/webmention" />
<link rel="pingback" href="https://webmention.io/mabbs.github.io/xmlrpc" />
<link rel="preconnect" href="https://summary.mayx.eu.org" crossorigin="anonymous" />
<link rel="prefetch" href="https://www.blogsclub.org/badge/mabbs.github.io" as="image" />
<link rel="blogroll" type="text/xml" href="/blogroll.opml" />
<link rel="me" href="https://github.com/Mabbs" />
<script src="/assets/js/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
var lastUpdated = new Date("Thu, 01 Jan 2026 00:00:18 +0800");
var BlogAPI = "https://summary.mayx.eu.org";
</script>
<script src="/assets/js/main.js"></script>
<!--[if !IE]> -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-137710294-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-137710294-1');
</script>
<script src="/assets/js/instant.page.js" type="module"></script>
<!-- <![endif]-->
</head>
<body>
<!--[if !IE]> --><noscript><marquee style="top: -15px; position: relative;"><small>发现当前浏览器没有启用JavaScript这不影响你的浏览但可能会有一些功能无法使用……</small></marquee></noscript><!-- <![endif]-->
<!--[if IE]><marquee style="top: -15px; position: relative;"><small>发现当前浏览器为Internet Explorer这不影响你的浏览但可能会有一些功能无法使用……</small></marquee><![endif]-->
<div class="wrapper">
<header class="h-card">
<h1><a class="u-url u-uid p-name" rel="me" href="/">Mayx的博客</a></h1>
<img src="https://avatars0.githubusercontent.com/u/17966333" fetchpriority="high" class="u-photo" alt="Logo" style="width: 90%; max-width: 300px; max-height: 300px;" />
<p class="p-note">Mayx's Home Page</p>
<form action="/search.html">
<input type="text" name="keyword" id="search-input-all" placeholder="Search blog posts.." />&#160;<input type="submit" value="搜索" />
</form>
<br />
<p class="view"><a class="u-url" href="/Mabbs/">About me</a></p>
<ul class="downloads">
<li style="width: 270px; border-right: none;"><a href="/MayxBlog.tgz">Download <strong>TGZ File</strong></a></li>
</ul>
</header>
<section class="h-entry">
<small><time class="date dt-published" datetime="2019-11-21T00:00:00+08:00">21 November 2019</time> - 字数统计1468 - 阅读大约需要5分钟 - Hits: <span id="/2019/11/21/enc.html" class="visitors">Loading...</span></small>
<h1 class="p-name">Web Crypto Api学习笔记</h1>
<p class="view">by <a class="p-author h-card" href="//github.com/Mabbs">mayx</a></p>
<div id="outdate" style="display:none;">
<hr /><p>
这是一篇创建于 <span id="outime"></span> 天前的文章,其中的信息可能已经有所发展或是发生改变。
</p>
</div>
<script>
daysold = Math.floor((new Date().getTime() - new Date("Thu, 21 Nov 2019 00:00:00 +0800").getTime()) / (24 * 60 * 60 * 1000));
if (daysold > 90) {
document.getElementById("outdate").style.display = "block";
document.getElementById("outime").innerHTML = daysold;
}
</script>
<hr />
<b>AI摘要</b>
<p id="ai-output">这篇文章是作者在学习Web Crypto API时的笔记讲述了自己在制作分布式加密邮件系统的过程中遇到的挑战特别是对JavaScript特别是其对象系统和ArrayBuffer/Uint8Array等概念的不适应。作者提到Javascript语法与自己习惯的Linux Shell语言对比存在差异导致在处理Web Crypto API时感到困惑尤其是其复杂的参数要求如密码长度和初始向量。通过Copy&Paste的方式作者勉强完成了一个加密消息的示例代码同时表达了继续学习的决心。整个过程中作者流露出对学习过程的艰辛和对未来的期待。</p>
<hr />
<ul><li><a href="#学习前">学习前</a></li><li><a href="#学习过程">学习过程</a></li><li><a href="#辣鸡代码">辣鸡代码</a></li><li><a href="#感想">感想</a></li></ul>
<hr />
<main class="post-content e-content" role="main"><p>感觉要爆炸了……<!--more--></p>
<h1 id="学习前">
<a href="#学习前"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 学习前
</h1>
<p>在四个月前,我作了<a href="/2019/07/02/encmail.html">制作分布式加密邮件系统的计划</a>,不过现在来看,这怕是得变成五年计划了…… </p><p>
Javascript是真的垃圾搞一堆对象各种各样的对象让人无言以对不过也可能因为我以前用的是Linux Shell语言那个语言在我学了Python之后还是感觉很舒服因为它不用管变量类型Bash之类的解析器会把它们一律看作字符串遇到要运算的部分才会转换为数字。除此之外它连接字符串是什么都不用加不需要考虑变量是什么类型只要解析器能分辨变量它就能正常工作也不需要什么强制转换之类乱七八糟的东西而且它更没有什么乱七八糟的对象之类的概念。 <del>(跑题了:-P</del> </p><p>
不过浏览器只支持Javascript语言……没办法看来只能动用我的Copy&amp;Paste大法了。不过国内用Web Crypto Api的人好少找了半天也没有什么示例可以Copy……没办法那我只好去抄<a href="https://mdn.github.io/dom-examples/web-crypto/">官方示例</a>了……</p>
<h1 id="学习过程">
<a href="#学习过程"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 学习过程
</h1>
<p>我在大学中也加了那么一个社团/协会在社团办公室里虽然没人能帮助我学习Javascript不过那里有多余的屏幕然后我就体验了一下双屏幕工作的感觉那个感觉还是挺不错的也可能是我的屏幕分辨率太低了是1366x768的垃圾屏幕……一个屏幕打代码另一个看网页效果还是挺不错的至少不用不停的切换窗口了。 </p><p>
看着示例代码我感觉真是要爆炸了各种奇葩的对象像什么ArrayBuffer还是什么Uint8Array啥的还有一堆乱七八糟要求的格式密码长度还必须是16的倍数而且还有什么初始向量iv……真的是一言难尽…… </p><p>
不过我还是发挥了作为辣鸡程序员的特长——Copy&amp;Paste大法最终可算是拼凑出了一个看起来勉强能用的代码……</p>
<h1 id="辣鸡代码">
<a href="#辣鸡代码"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 辣鸡代码
</h1>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">getByteLen</span><span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">len</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">val</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">val</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">match</span><span class="p">(</span><span class="sr">/</span><span class="se">[^\x</span><span class="sr">00-</span><span class="se">\x</span><span class="sr">ff</span><span class="se">]</span><span class="sr">/ig</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="nx">len</span> <span class="o">+=</span> <span class="mi">3</span><span class="p">;</span>
<span class="k">else</span> <span class="nx">len</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">len</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">importSecretKey</span><span class="p">(</span><span class="nx">rawKey</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">window</span><span class="p">.</span><span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">.</span><span class="nx">importKey</span><span class="p">(</span>
<span class="dl">"</span><span class="s2">raw</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">rawKey</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">AES-GCM</span><span class="dl">"</span><span class="p">,</span>
<span class="kc">true</span><span class="p">,</span>
<span class="p">[</span><span class="dl">"</span><span class="s2">encrypt</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">decrypt</span><span class="dl">"</span><span class="p">]</span>
<span class="p">);</span>
<span class="p">}</span>
<span class="k">async</span> <span class="kd">function</span> <span class="nx">encryptMessage</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">iv</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">crypto</span><span class="p">.</span><span class="nx">getRandomValues</span><span class="p">(</span><span class="k">new</span> <span class="nb">Uint8Array</span><span class="p">(</span><span class="mi">12</span><span class="p">));</span>
<span class="nx">ciphertext</span> <span class="o">=</span> <span class="k">await</span> <span class="nb">window</span><span class="p">.</span><span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">.</span><span class="nx">encrypt</span><span class="p">(</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">AES-GCM</span><span class="dl">"</span><span class="p">,</span>
<span class="na">iv</span><span class="p">:</span> <span class="nx">iv</span>
<span class="p">},</span>
<span class="nx">key</span><span class="p">,</span>
<span class="nx">encoded</span>
<span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">ciphertext</span><span class="p">)</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">secretKey</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">enc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">TextEncoder</span><span class="p">();</span>
<span class="nx">keyword</span><span class="o">=</span><span class="dl">"</span><span class="s2">Mayx</span><span class="dl">"</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">getByteLen</span><span class="p">(</span><span class="nx">keyword</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">keyword</span> <span class="o">=</span> <span class="nx">keyword</span> <span class="o">+</span> <span class="dl">"</span><span class="se">\</span><span class="s2">0</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">rawKey</span> <span class="o">=</span> <span class="nx">enc</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="nx">keyword</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">encoded</span> <span class="o">=</span> <span class="nx">enc</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="dl">"</span><span class="s2">Mayx is Good</span><span class="dl">"</span><span class="p">);</span>
<span class="p">(</span><span class="k">async</span> <span class="p">()</span> <span class="o">=&gt;</span> <span class="p">{</span>
<span class="nx">secretKey</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">importSecretKey</span><span class="p">(</span><span class="nx">rawKey</span><span class="p">);</span>
<span class="nx">encryptMessage</span><span class="p">(</span><span class="nx">secretKey</span><span class="p">);</span>
<span class="p">})();</span>
</code></pre></div></div>
<h1 id="感想">
<a href="#感想"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 感想
</h1>
<p>路漫漫其修远兮,吾将上下而求索,我还是要继续加油啊!</p></main>
<small style="display: block">tags: <a rel="category tag" class="p-category" href="/search.html?keyword=%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0"><em>学习笔记</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=Web%20Crypto%20Api"><em>Web Crypto Api</em></a> <span style="float: right;"><a href="https://gitlab.com/mayx/mayx.gitlab.io/tree/master/_posts/2019-11-21-enc.md">查看原始文件</a></span></small>
<h4 style="border-bottom: 1px solid #e5e5e5;margin: 2em 0 5px;">推荐文章</h4>
<p id="suggest-container">Loading...</p>
<script>
var suggest = $("#suggest-container");
$.get(BlogAPI + "/suggest?id=/2019/11/21/enc.html&update=" + lastUpdated.valueOf(), function (data) {
if (data.length) {
getSearchJSON(function (search) {
suggest.empty();
var searchMap = {};
for (var i = 0; i < search.length; i++) {
searchMap[search[i].url] = search[i];
}
var tooltip = $('<div class="content-tooltip"></div>').appendTo('body').hide();
for (var j = 0; j < data.length; j++) {
var item = searchMap[data[j].id];
if (item) {
var link = $('<a href="' + item.url + '">' + item.title + '</a>');
var contentPreview = item.content.substring(0, 100);
if (item.content.length > 100) {
contentPreview += "……";
}
link.hover(
function(e) {
tooltip.text($(this).data('content'))
.css({
top: e.pageY + 10,
left: e.pageX + 10
})
.show();
},
function() {
tooltip.hide();
}
).mousemove(function(e) {
tooltip.css({
top: e.pageY + 10,
left: e.pageX + 10
});
}).data('content', contentPreview);
suggest.append(link);
suggest.append(' - ' + item.date + '<br />');
}
}
});
} else {
suggest.html("暂无推荐文章……");
}
});
</script>
<br />
<div class="pagination">
<span class="prev">
<a href="/2019/11/18/archive.html">
上一篇Bug Forever
</a>
</span>
<br />
<span class="next">
<a href="/2019/12/04/abuse.html">
下一篇:废人的研究
</a>
</span>
</div>
<!--[if !IE]> -->
<link rel="stylesheet" href="/assets/css/gitalk.css">
<script src="/assets/js/gitalk.min.js"></script>
<div id="gitalk-container"></div>
<script>
var gitalk = new Gitalk({
clientID: '36557aec4c3cb04f7ac6',
clientSecret: 'ac32993299751cb5a9ba81cf2b171cca65879cdb',
repo: 'mabbs.github.io',
owner: 'Mabbs',
admin: ['Mabbs'],
id: '/2019/11/21/enc', // Ensure uniqueness and length less than 50
distractionFreeMode: false, // Facebook-like distraction free mode
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
})
gitalk.render('gitalk-container')
</script>
<!-- <![endif]-->
</section>
<!--[if !IE]> -->
<div id="landlord" style="left:5px;bottom:0px;">
<div class="message" style="opacity:0"></div>
<canvas id="live2d" width="500" height="560" class="live2d"></canvas>
<div class="live_talk_input_body">
<form id="live_talk_input_form">
<div class="live_talk_input_name_body" >
<input type="checkbox" id="load_this" />
<input type="hidden" id="post_id" value="/2019/11/21/enc.html" />
<label for="load_this">
<span style="font-size: 11px; color: #fff;">&#160;想问这篇文章</span>
</label>
</div>
<div class="live_talk_input_text_body">
<input name="talk" type="text" class="live_talk_talk white_input" id="AIuserText" autocomplete="off" placeholder="要和我聊什么呀?" />
<button type="submit" class="live_talk_send_btn" id="talk_send">发送</button>
</div>
</form>
</div>
<input name="live_talk" id="live_talk" value="1" type="hidden" />
<div class="live_ico_box" style="display:none;">
<div class="live_ico_item type_info" id="showInfoBtn"></div>
<div class="live_ico_item type_talk" id="showTalkBtn"></div>
<div class="live_ico_item type_music" id="musicButton"></div>
<div class="live_ico_item type_youdu" id="youduButton"></div>
<div class="live_ico_item type_quit" id="hideButton"></div>
<input name="live_statu_val" id="live_statu_val" value="0" type="hidden" />
<audio src="" style="display:none;" id="live2d_bgm" data-bgm="0" preload="none"></audio>
<input id="duType" value="douqilai" type="hidden" />
</div>
</div>
<div id="open_live2d">召唤伊斯特瓦尔</div>
<!-- <![endif]-->
<footer>
<p>
<small>Made with ❤ by Mayx<br />Last updated at 2026-01-01 00:00:18<br /> 总字数614622 - 文章数178 - <a href="/atom.xml" >Atom</a> - <a href="/README.html" >About</a></small>
</p>
</footer>
</div>
<script src="/assets/js/scale.fix.js"></script>
<!--[if !IE]> -->
<script src="/assets/js/main_new.js"></script>
<script src="/Live2dHistoire/live2d/js/live2d.js"></script>
<script src="/Live2dHistoire/live2d/js/message.js"></script>
<!-- <![endif]-->
</body>
</html>