mirror of
https://github.com/Mabbs/mabbs.github.io
synced 2026-07-22 03:33:22 +08:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b666bd16b2 | |||
| bc094788c2 | |||
| c0b1009935 | |||
| 129c4d1b5b | |||
| a8b9118a20 | |||
| dff8a2d2c9 | |||
| 2952d9f63e | |||
| 3de3d63d77 | |||
| 3dab9f333a | |||
| 85aa965218 | |||
| 0e065bf282 | |||
| 680afdca5a | |||
| 9e7e727897 | |||
| f5accbcad4 | |||
| d3ef0a278b | |||
| 38c549606e | |||
| 443d65ac50 | |||
| c8ce8de1d9 | |||
| 03d9517241 | |||
| 9b9efd0f60 | |||
| 07a3d18350 | |||
| 550321e80a | |||
| 50c6c49c4c | |||
| 593b4fa003 | |||
| 46f1b8d742 | |||
| 7a525073f9 | |||
| dc37b70586 |
@@ -79,7 +79,7 @@
|
||||
background-color: rgba(74, 59, 114,0.9);
|
||||
}
|
||||
.live_talk_input_name_body{
|
||||
width:70px;
|
||||
width:100px;
|
||||
box-sizing:border-box;
|
||||
height:24px;
|
||||
border: 2px solid rgb(223, 179, 241);
|
||||
|
||||
@@ -158,7 +158,7 @@ if(!norunFlag){
|
||||
function showHitokoto(){
|
||||
if(sessionStorage.getItem("Sleepy")!=="1"){
|
||||
if(!AITalkFlag){
|
||||
$.getJSON('https://v1.hitokoto.cn/',function(result){
|
||||
$.getJSON('https://hitokoto.mayx.eu.org/',function(result){
|
||||
talkValTimer();
|
||||
showMessage(result.hitokoto, 0);
|
||||
});
|
||||
@@ -188,7 +188,26 @@ if(!norunFlag){
|
||||
if(Array.isArray(text)) text = text[Math.floor(Math.random() * text.length + 1)-1];
|
||||
//console.log('showMessage', text);
|
||||
$('.message').stop();
|
||||
$('.message').html(text);
|
||||
if(text instanceof EventSource){
|
||||
var outputContainer = $('.message')[0];
|
||||
var eventFlag = false;
|
||||
text.onmessage = (event) => {
|
||||
if (event.data == "[DONE]") {
|
||||
text.close();
|
||||
return;
|
||||
} else {
|
||||
if(!eventFlag){
|
||||
talkValTimer();
|
||||
outputContainer.textContent = "";
|
||||
eventFlag = true;
|
||||
}
|
||||
const data = JSON.parse(event.data);
|
||||
outputContainer.textContent += data.response;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$('.message').html(text);
|
||||
}
|
||||
$('.message').fadeTo(200, 1);
|
||||
//if (timeout === null) timeout = 5000;
|
||||
//hideMessage(timeout);
|
||||
@@ -275,36 +294,18 @@ if(!norunFlag){
|
||||
});
|
||||
$('#talk_send').on('click',function(){
|
||||
var info_ = $('#AIuserText').val();
|
||||
var userid_ = $('#AIuserName').val();
|
||||
// var userid_ = $('#AIuserName').val();
|
||||
let add_id = "";
|
||||
if($('#load_this').prop("checked")){
|
||||
add_id = "&id="+encodeURIComponent($('#post_id').val());
|
||||
}
|
||||
if(info_ == "" ){
|
||||
showMessage('写点什么吧!',0);
|
||||
return;
|
||||
}
|
||||
if(userid_ == ""){
|
||||
showMessage('聊之前请告诉我你的名字吧!',0);
|
||||
return;
|
||||
}
|
||||
showMessage('思考中~', 0);
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: talkAPI,
|
||||
data: {
|
||||
"info": info_,
|
||||
"userId": userid_
|
||||
},
|
||||
success: function(res) {
|
||||
if(res.intent.code !== 0){
|
||||
talkValTimer();
|
||||
showMessage('似乎有什么错误,请和站长联系!',0);
|
||||
}else{
|
||||
talkValTimer();
|
||||
showMessage(res.results[0].values.text,0);
|
||||
}
|
||||
console.log(res);
|
||||
$('#AIuserText').val("");
|
||||
sessionStorage.setItem("live2duser", userid_);
|
||||
}
|
||||
});
|
||||
const evSource = new EventSource(talkAPI + "?info=" + encodeURIComponent(info_) + add_id);
|
||||
showMessage(evSource);
|
||||
});
|
||||
}else{
|
||||
$('#showInfoBtn').hide();
|
||||
@@ -379,11 +380,11 @@ if(!norunFlag){
|
||||
showMessage('音乐似乎加载不出来了呢!',0);
|
||||
});
|
||||
}
|
||||
//获取用户名
|
||||
var live2dUser = sessionStorage.getItem("live2duser");
|
||||
if(live2dUser !== null){
|
||||
$('#AIuserName').val(live2dUser);
|
||||
}
|
||||
// //获取用户名
|
||||
// var live2dUser = sessionStorage.getItem("live2duser");
|
||||
// if(live2dUser !== null){
|
||||
// $('#AIuserName').val(live2dUser);
|
||||
// }
|
||||
//获取位置
|
||||
var landL = sessionStorage.getItem("historywidth");
|
||||
var landB = sessionStorage.getItem("historyheight");
|
||||
|
||||
@@ -16,13 +16,16 @@ Powered by [Jekyll](https://github.com/jekyll/jekyll)
|
||||
[Simple-Jekyll-Search](https://github.com/christian-fei/Simple-Jekyll-Search)
|
||||
|
||||
## 使用的网络资源
|
||||
[Github](https://github.com/) | 包含:
|
||||
[Github](https://github.com/) | 包含:
|
||||
- Issue
|
||||
- Pages
|
||||
- Git
|
||||
|
||||
|
||||
[Cloudflare](https://www.cloudflare.com/) | 包含:
|
||||
- CDN、规则以及缓存
|
||||
- Workers、D1 SQL 数据库、Vectorize 数据库、AI
|
||||
|
||||
[网易云音乐](https://music.163.com/)
|
||||
[一言](https://hitokoto.cn/)
|
||||
[CDNJS](https://cdnjs.com/)
|
||||
[unpkg](https://unpkg.com/)
|
||||
|
||||
|
||||
+19
-2
@@ -27,6 +27,19 @@
|
||||
|
||||
gtag('config', '{{ site.google_analytics }}');
|
||||
var lastUpdated = new Date("{{ site.time | date: "%FT%T%z" }}");
|
||||
var BlogAPI = "https://summary.mayx.eu.org";
|
||||
function getSearchJSON(callback) {
|
||||
var searchData = JSON.parse(localStorage.getItem("blog_" + lastUpdated.valueOf()));
|
||||
if (!searchData) {
|
||||
localStorage.clear();
|
||||
$.getJSON("/search.json", function (data) {
|
||||
localStorage.setItem("blog_" + lastUpdated.valueOf(), JSON.stringify(data));
|
||||
callback(data);
|
||||
});
|
||||
} else {
|
||||
callback(searchData);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
<style>
|
||||
@@ -99,8 +112,12 @@
|
||||
<div class="message" style="opacity:0"></div>
|
||||
<canvas id="live2d" width="500" height="560" class="live2d"></canvas>
|
||||
<div class="live_talk_input_body">
|
||||
<div class="live_talk_input_name_body" style="display:none;">
|
||||
<input name="name" type="hidden" class="live_talk_name white_input" id="AIuserName" value="Mayx_Blog_Talk" />
|
||||
<div class="live_talk_input_name_body" {% unless page.layout == "post" %}style="display:none;"{% endunless %}>
|
||||
<input type="checkbox" id="load_this">
|
||||
<input type="hidden" id="post_id" value="{{ page.url }}">
|
||||
<label for="load_this">
|
||||
<span style="font-size: 11px; color: #fff;"> 想问这篇文章</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="要和我聊什么呀?"/>
|
||||
|
||||
+36
-8
@@ -44,15 +44,15 @@ layout: default
|
||||
var postContent = "文章标题:" + {{ page.title | jsonify }} + ";文章内容:" + {{ page.content | strip_html | strip_newlines | jsonify }};
|
||||
var postContentSign = await sha(postContent);
|
||||
var outputContainer = document.getElementById("ai-output");
|
||||
$.get("https://summary.mayx.eu.org/is_uploaded?id={{ page.url }}&sign=" + postContentSign, function (data) {
|
||||
$.get(BlogAPI + "/is_uploaded?id={{ page.url }}&sign=" + postContentSign, function (data) {
|
||||
if (data == "yes") {
|
||||
$.get("https://summary.mayx.eu.org/get_summary?id={{ page.url }}&sign=" + postContentSign, function (data2) {
|
||||
$.get(BlogAPI + "/get_summary?id={{ page.url }}&sign=" + postContentSign, function (data2) {
|
||||
outputContainer.textContent = data2;
|
||||
});
|
||||
} else {
|
||||
$.post("https://summary.mayx.eu.org/upload_blog?id={{ page.url }}", postContent, function (data) {
|
||||
$.get("https://summary.mayx.eu.org/get_summary?id={{ page.url }}&sign=" + postContentSign);
|
||||
const evSource = new EventSource("https://summary.mayx.eu.org/summary?id={{ page.url }}");
|
||||
$.post(BlogAPI + "/upload_blog?id={{ page.url }}", postContent, function (data) {
|
||||
$.get(BlogAPI + "/get_summary?id={{ page.url }}&sign=" + postContentSign);
|
||||
const evSource = new EventSource(BlogAPI + "/summary?id={{ page.url }}");
|
||||
outputContainer.textContent = "";
|
||||
evSource.onmessage = (event) => {
|
||||
if (event.data == "[DONE]") {
|
||||
@@ -80,7 +80,33 @@ layout: default
|
||||
{% if page.tags %}
|
||||
<small>tags: <em>{{ page.tags | join: "</em> - <em>" }}</em></small>
|
||||
{% endif %}
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<p id="suggest-container"></p>
|
||||
<script>
|
||||
var blogurl = "{{ page.url }}";
|
||||
var suggest = $("#suggest-container")[0];
|
||||
suggest.innerHTML = "Loading...";
|
||||
$.get(BlogAPI + "/suggest?id=" + blogurl + "&update=" + lastUpdated.valueOf(), function (data) {
|
||||
if (data.length) {
|
||||
getSearchJSON(function (search) {
|
||||
suggest.innerHTML = '<b>推荐文章</b><hr style="margin: 0 0 5px"/>';
|
||||
const searchMap = new Map(search.map(item => [item.url, item]));
|
||||
const merged = data.map(suggestObj => {
|
||||
const searchObj = searchMap.get(suggestObj.id);
|
||||
return searchObj ? { ...searchObj } : null;
|
||||
});
|
||||
merged.forEach(element => {
|
||||
if (element) {
|
||||
suggest.innerHTML += "<a href=" + element.url + ">" + element.title + "</a> - " + element.date + "<br />";
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
suggest.innerHTML = "暂无推荐文章……";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<div class="pagination">
|
||||
{% if page.previous.url %}
|
||||
<span class="prev">
|
||||
@@ -114,7 +140,8 @@ layout: default
|
||||
owner: 'Mabbs',
|
||||
admin: ['Mabbs'],
|
||||
id: '{{ page.id }}', // Ensure uniqueness and length less than 50
|
||||
distractionFreeMode: false // Facebook-like distraction free mode
|
||||
distractionFreeMode: false, // Facebook-like distraction free mode
|
||||
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
|
||||
})
|
||||
}
|
||||
else {
|
||||
@@ -125,7 +152,8 @@ layout: default
|
||||
owner: 'Mabbs',
|
||||
admin: ['Mabbs'],
|
||||
id: '{{ page.id }}', // Ensure uniqueness and length less than 50
|
||||
distractionFreeMode: false // Facebook-like distraction free mode
|
||||
distractionFreeMode: false, // Facebook-like distraction free mode
|
||||
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ export default {
|
||||
不过毕竟Workers本身是有每日调用次数限制的,自己部署当然更好。方法也很简单,首先在D1里创建一个数据库,然后创建一个Workers,在变量里绑定AI和新建的D1数据库,名字要起成blog_summary,如果想换名字就要改代码,里面建一张叫做blog_summary的表,需要有3个字段,分别是id、content、summary,都是text类型,如果想用博客计数器功能就再加一张counter表,一个是url,text类型,另一个是counter,int类型。本来博客计数器接口名字也打算用counter的,结果不知道AdBlock有什么大病,居然会屏蔽“counter?id=”这样的请求😆,害的我只能改成count_click这样的名字了。
|
||||
|
||||
# 其他想法
|
||||
加了这个功能之后感觉效果还挺不错的,这下就有点想加点别的功能了,比如文章推荐和知识库问答啥的,不过这个似乎需要什么向量数据库,而且数据需要进行“嵌入”处理,这用现有的东西感觉难度实在是太高了所以就算了……另外还想用文生图模型给我的文章加个头图,不过我天天写的都是些技术文章,没啥图可加吧🤣。其他的之后再看看有什么有意思的功能再加吧。
|
||||
加了这个功能之后感觉效果还挺不错的,这下就有点想加点别的功能了,比如文章推荐和知识库问答啥的, ~~不过这个似乎需要什么向量数据库,而且数据需要进行“嵌入”处理,这用现有的东西感觉难度实在是太高了所以就算了……~~ (在2024.09.27中[已经实现了](/2024/09/27/rag.html)) 另外还想用文生图模型给我的文章加个头图,不过我天天写的都是些技术文章,没啥图可加吧🤣。其他的之后再看看有什么有意思的功能再加吧。
|
||||
|
||||
# 感想
|
||||
Cloudflare真不愧是赛博活佛,这波操作下来不就省下了那笔生成费用?啥都是免费的,不过问题就是Cloudflare在这方面几乎是垄断地位,虽然国际大厂倒是不担心倒闭,不过万一挂了想再找个这样厉害的平台可就没了😆。
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
layout: post
|
||||
title: 华为仓颉语言使用体验
|
||||
tags: [华为, 仓颉, 体验]
|
||||
---
|
||||
|
||||
看看“自研”的轮子有什么特别之处?<!--more-->
|
||||
|
||||
# 起因
|
||||
前段时间因为华为对它的仓颉编程语言开启了公测(公开内测),随后媒体又吹了一波。虽然华为最近也整了好多乱七八糟的东西,但至少我没有亲眼见过。既然这个仓颉的编译器公测了我就申请试试看呗,反正编译器又不需要特定的设备或者系统运行。
|
||||
申请之后过了几天就通过了,然后编译器的安装包就可以在GitCode上下载。目前看起来没有开源,可以在Windows x64,macOS和Linux的x64和aarch64上运行和编译,另外也支持它的那个鸿蒙Next系统,虽然我申请了那个插件也通过了,但是毕竟没有真机,而且那个IDE挺大的也就算有模拟器可以用也懒得试😂。
|
||||
|
||||
# 编写体验
|
||||
首先我下了Windows版的编译器,安装好之后看了看文档,感觉语法倒是没什么复杂的,不过和Python差别还是挺大的,所以还是得看着文档写😂。看了一圈之后首先写个九九乘法表试试看:
|
||||
```kotlin
|
||||
main() {
|
||||
for (i in 1..10) {
|
||||
for (j in 1..i + 1) {
|
||||
print("${j}*${i}=${i*j}\t")
|
||||
}
|
||||
println()
|
||||
}
|
||||
}
|
||||
```
|
||||
编译之后运行倒是没什么问题,随后再写个递归版的试试看:
|
||||
```kotlin
|
||||
func row(i: Int): Unit{
|
||||
if(i < 10){
|
||||
col(i, 1)
|
||||
println()
|
||||
row(i + 1)
|
||||
}
|
||||
}
|
||||
|
||||
func col(i:Int, j:Int): Unit{
|
||||
if(i >= j){
|
||||
print("${j}*${i}=${i*j}\t")
|
||||
col(i, j + 1)
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
row(1)
|
||||
}
|
||||
```
|
||||
运行也没有问题,那就试试看把编译的产物放别的电脑运行试试看?结果就不能运行了。似乎是依赖了“libcangjie-runtime”和“libsecurec”这两个库,即使是在编译选项里开了静态编译也没有用,因为SDK里没有这两个的静态库文件,而且也没有它们的源代码……像Golang都是静态编译没有什么乱七八糟的依赖的啊……
|
||||
另外我在Github上搜了一下,“libsecurec”这个库是有源代码的,叫做[libboundscheck](https://github.com/openeuler-mirror/libboundscheck),看名字是用来字符边界检查之类的库,似乎华为很多产品里都有用,在这个SDK里用的是[这个](https://github.com/openeuler-mirror/libboundscheck/tree/5701ca210dfb71037f3cb3340166d150917e8a4d)版本。
|
||||
不过如果仓颉主要是给鸿蒙Next用的话,那个系统应该是预先有装仓颉的运行环境的,应该不静态编译也行。
|
||||
|
||||
# 对仓颉语言的看法
|
||||
单从我上面写的这点代码看的话这语法比C都复杂😂,看了一下文档乱七八糟的概念还挺多,毕竟是融合了各种各样的语言,有Java的复杂,支持什么注解和反射之类的,还有TS的声明类型,变量还要指定变不变啥的,不过似乎没有关于异步的语法,可能是用线程弥补吧?其他近些年出的语言我没怎么接触过所以其他的不太清楚,不过让AI看了看我写的那段代码它说像Kotlin,然后讨论群里又说借鉴了50%的Rust🤣,确实融合的有点多。另外据说除了编译成机器码(CJNative)外还能编译成字节码(CJVM),不过CJVM在内测,不知道到时候会不会正式发布……除此之外也能调C和Python的库,似乎是用的FFI调用,可以不用单独开个进程然后去获得输出的值,效率应该还是挺高的。
|
||||
但是要说这个语言有什么特别之处目前似乎也看不出来,不过毕竟仓颉语言算是给鸿蒙Next系统用的,学着iOS/macOS整Swift那样吧,但是在苹果系开发要想用苹果的框架,可能Swift是最好的选项。鸿蒙Next除了这个还整的什么ArkTS(那个可能算是小程序吧,毕竟那个没见过不知道底层是怎么运行的),至于鸿蒙Next能不能用其他语言开发目前也不知道(倒是能用NDK),要是能的话大家肯定是用现有已经开发好的改改然后移植到鸿蒙Next吧(前提是这些公司认为用鸿蒙Next的人使用他们的软件有足够的收益),如果不行从头开发成本就更高了,估计得劝退一大堆公司。毕竟鸿蒙Next没有历史,和Android以及iOS根本不能比,而且相比也没有解决什么痛点,另外其他手机厂商也不会考虑使用鸿蒙Next,只能像苹果一样搞成仅自家使用的系统。但是用户量根本和iPhone不能比,公司可不会听华为在网上的营销,毕竟公司是要实实在在赚钱的,靠营销只能忽悠普通人(但要是普通人买来发现除了国内大厂的软件其他软件全不能用估计也没人买了🤣)。
|
||||
另外鸿蒙Next好像也会搞PC版,就像Mac那样。不过Mac是正经啥语言写的都能运行,而且相对还是挺开放的,到时候如果PC版的鸿蒙Next连终端个也没有,而且只能运行仓颉语言写的软件那怕是比其他Linux发行版还废了🤣。
|
||||
不过如果用户侧如果搞不好的话说不定可以在服务器上用,毕竟服务器的话只在乎能不能写出这个软件,至于用什么语言写其实不重要,只要性能好就行,如果华为能整一批写仓颉的学生,还能把该整的库整好,也许会有公司考虑用,在做政府相关的项目说不定可以作为卖点🤣。
|
||||
|
||||
# 感想
|
||||
虽然说华为整的这堆莫名其妙的东西也许没什么用,或者也可能会有些用,不过毕竟搞这些东西已经算是用公司的前景去赌未来了,虽然拿这些东西搞营销很恶心,但目前来看至少确实是有在也许没回报的东西上投真金白银的,还是挺厉害的。
|
||||
但正因为它们营销搞太多了,到时候因为搞这些东西把公司玩死了我觉得也是大快人心的🤣🤣🤣。
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
layout: post
|
||||
title: Mac mini 2018使用体验
|
||||
tags: [Apple, Mac, 体验]
|
||||
---
|
||||
|
||||
买个快过时的产品是什么感受🤣<!--more-->
|
||||
|
||||
# 起因
|
||||
最近由于某些原因需要一个装有macOS的电脑用来开发,虽然我自己[有MacBook Pro](/2023/02/03/mbp.html),但是我不太想让我的电脑上装一堆乱七八糟的环境,而且我的Mac只有8GiB内存😅,也不适合整比较复杂的东西。那既然这样上次不是[整了个黑苹果](/2024/06/16/hackintosh.html)吗?但是考虑到黑苹果不太可靠,可能更新着系统就挂了,而且用APFS文件还不好拷出来。那既然买白苹果是不是还是买M芯片的Mac mini比较好?但是这次开发的程序原来是在Intel的Mac上开发的,虽然有Rosetta 2,但是怕出一些莫名其妙的问题,然后再考虑到以后可能要升macOS 15(macOS 16应该就不再支持Intel的Mac了),所以最后还是整了个二手的8+512的Mac mini 2018(i5-8500B版)。
|
||||
|
||||
# 更换内存
|
||||
刚拿到手的时候是8GiB内存,显然有点小了,不过Mac mini 2018是支持自己更换内存的,所以又额外买了两条16GiB内存。东西都到了之后就打算直接拆开来换,结果发现我手头没有T6H的螺丝刀🤣。我之前有买过一个很便宜的25合1的螺丝刀套装,里面包含梅花螺丝批头,但是没想到这个Mac mini上的螺丝上面有个柱子,普通的T6螺丝刀根本插不进去。没办法只好单独买了这个螺丝刀……在拿到螺丝刀之前,我觉得还是得看看教程,所以网上搜了个[iFixit的教程](https://zh.ifixit.com/Guide/Mac+mini+Late+2018+%E7%89%88%E5%86%85%E5%AD%98%E6%9B%B4%E6%8D%A2/115309),看了一下还好只有外壳的螺丝是带柱子的,不然又得买😂。
|
||||
最后东西到齐之后按照上面的教程把内存换了,这下就成了32+512的Mac mini了,也算够用了。
|
||||
|
||||
# 使用体验
|
||||
作为最后一代Intel的Mac,这个Mac mini其实和黑苹果的区别也就是T2芯片了。但要说这个T2芯片到底在使用体验上有啥区别,目前来看只能说几乎没有……当然不是完全没有,因为装有T2芯片以及之后的M芯片的Mac硬盘默认都是加了密的,所以在开启文件保险箱的时候瞬间就能打开,不需要额外的加密过程。黑苹果虽然也支持文件保险箱,似乎是装“AppleKeyFeeder-64.efi”这个驱动就可以,先不说这个东西会不会出问题,至少它在加解密的过程中需要占用CPU,在这个Mac上它的加解密都是在这个T2芯片上进行的,所以不会影响CPU性能,其实这要比Windows的Bitlocker要好一些,现在预装Windows的电脑基本上默认就开了Bitlocker,但使用肯定是要用CPU进行加解密的,多多少少会影响一点性能,在这个Mac上就不会有问题了。
|
||||
除此之外就是无线网络了,我装的黑苹果是在台式机上装的,没有无线网卡,当然隔空投送也用不了。白苹果就可以,而且很快,我试了一下从我的MacBook传到Mac Mini速度最高可以达到400Mbps,当然和现在的Wi-Fi相比不算很快,但是在我用的设备里面已经算快的了 ~~(用的全是垃圾🤣)~~
|
||||
另外我还听说T2芯片在视频编解码上有额外的优势,不过这个我没法测,毕竟买它又不是为了剪辑的,至于看视频基本上只要支持硬件解码,看4K视频都不会有压力,反正我试了我的黑苹果看4K也没有卡。
|
||||
其他部分和黑苹果几乎没什么区别,毕竟都是Intel的芯片,黑苹果不能干的白苹果一样也不能干,没有因为多出来一个T2芯片就多出来运行ARM程序的能力,至于装Windows……当然两边都能装,白苹果有启动转换,黑苹果本来就能直接装。接下来的话就只能希望苹果在下一个macOS版本更新中淘汰掉没有T2芯片的Intel的Mac,这样黑苹果就彻底完蛋了,而这个有T2芯片的就能发挥它最后的价值了,只不过目前来看黑苹果在macOS 15的Beta版仍然可以装,看来是没什么希望了🤣。
|
||||
|
||||
# 感想
|
||||
这么看来买这个Mac mini 2018似乎意义不大啊,不过毕竟要长期用,为了可靠性多花点钱也没什么问题,不过这个二手的Mac mini 2018居然比M1的Mac Mini还要贵😂,明明性能要更差啊……不过考虑到M芯片的加内存那么贵,而且这个Intel芯片的以后就算不用macOS还能装Windows,也许就是这个原因所以更贵吧?
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
layout: post
|
||||
title: Python国密算法使用探索
|
||||
tags: [Python, GmSSL, 国密]
|
||||
---
|
||||
|
||||
使用罕见的算法是什么感受😁<!--more-->
|
||||
|
||||
# 起因
|
||||
前段时间因为某些原因需要对某些东西进行密评改造,需要使用国密算法。虽然国密算法也算进入标准了,但是网上能搜到的资料还是太少了(尤其是Python的,大多资料都是Java的),所以我打算自己研究研究。
|
||||
|
||||
# 关于Python使用国密算法的方式
|
||||
其实在新版OpenSSL中已经支持了国密算法,比如SM3还有SM4,不过[pyOpenSSL](https://github.com/pyca/pyopenssl)似乎只有对非对称加密算法的支持……我倒是不在乎,因为在我实际应用里加解密都是服务器密码机处理的,我自己连密钥也看不到,所以不需要管怎么实现。但是签名验签还有摘要算法之类的理论上应该是可以自己实现的,毕竟算法是公开的。
|
||||
关于摘要算法SM3我搜了一下,似乎因为它已经进入标准了,至少在新版的Python中可以用`hashlib.new("sm3")`这样的方式进行计算,但是旧版的Python用不了……所以如果要在旧版Python上处理还得自己想办法。
|
||||
既然标准库不太能满足,那第三方库选哪个比较好呢?我看用的比较多的一个是封装C库[GmSSL](https://github.com/guanzhi/GmSSL)的[GmSSL-Python](https://github.com/GmSSL/GmSSL-Python),想要安装得先安装那个C库;还有一个是纯Python实现的[gmssl](https://github.com/duanhongyi/gmssl)。对我来说的话我更喜欢后面那个纯python实现的,虽然效率低了点,但是看起来比较简单(虽然看起来不是很专业🤣),那个C库包装的感觉有点复杂……而且这两个库有冲突,所以最终我选择了那个纯Python实现的版本。
|
||||
|
||||
# 使用SM2withSM3进行验签
|
||||
在一些挑战应答方式的登录方式中就需要用到这种东西,服务器发送一个随机数让客户端用私钥签名,然后服务器用公钥进行验签。我看了一下那个库的“gmssl.sm2.CryptSM2”中有个verify_with_sm3方法挺符合需求的,但有个问题是它这个CryptSM2传入的公钥是串数字,但客户端传来的是证书……看来还得解析证书,我看pyOpenSSL库里有加载证书还有导出公钥的方法,但是那个导出的公钥也不是一串数字……后来看了半天,发现导出的公钥的倒数130位才是公钥😅……最终把所有的值带进去试了一下终于没问题了,最终的代码如下:
|
||||
```python
|
||||
import OpenSSL.crypto
|
||||
from gmssl import sm2
|
||||
import base64
|
||||
|
||||
certSign = "" # 证书
|
||||
signBytes = b"" # 签名
|
||||
inData = b"" # 被签名的值
|
||||
|
||||
sm2.CryptSM2(
|
||||
private_key="",
|
||||
public_key=OpenSSL.crypto.dump_publickey(
|
||||
OpenSSL.crypto.FILETYPE_ASN1,
|
||||
OpenSSL.crypto.load_certificate(
|
||||
OpenSSL.crypto.FILETYPE_PEM,
|
||||
f"""-----BEGIN CERTIFICATE-----
|
||||
{certSign}
|
||||
-----END CERTIFICATE-----""".encode(),
|
||||
).get_pubkey(),
|
||||
).hex()[-128:],
|
||||
asn1=True,
|
||||
).verify_with_sm3(signBytes.hex(), inData)
|
||||
```
|
||||
|
||||
# 使用HMAC-SM3对数据进行消息验证
|
||||
这个其实新版的Python可以直接用,因为新版Python的hashlib里有SM3,所以一句
|
||||
```python
|
||||
hmac.new(key, data, digestmod="sm3").hexdigest()
|
||||
```
|
||||
就可以了,但是我用的是旧版的Python(macOS自带的3.9.6🤣)不支持……那怎么办呢?我看了一下这个函数的注释写的“digestmod”这个参数除了传hashlib支持的方法之外还可以传符合[PEP 247](https://peps.python.org/pep-0247/)的模块。显然无论是GmSSL-Python还是gmssl都没有符合这个规范。不过我可以自己写个适配器来适配这个规范。所以最终只好自己写一下了:
|
||||
```python
|
||||
import copy
|
||||
import hmac
|
||||
from gmssl import sm3
|
||||
|
||||
class sm3_adapter:
|
||||
def __init__(self):
|
||||
self.msg = []
|
||||
self.digest_size = 32
|
||||
self.block_size = 64
|
||||
|
||||
def new(self):
|
||||
self.msg = []
|
||||
|
||||
def update(self, data):
|
||||
self.msg += list(data)
|
||||
|
||||
def copy(self):
|
||||
return copy.deepcopy(self)
|
||||
|
||||
def digest(self):
|
||||
return bytes.fromhex(self.hexdigest())
|
||||
|
||||
def hexdigest(self):
|
||||
return sm3.sm3_hash(self.msg)
|
||||
|
||||
key = b"" # 密钥
|
||||
data = b"" # 数据
|
||||
hmac.new(key, data, digestmod=sm3_adapter).hexdigest()
|
||||
```
|
||||
|
||||
# 感想
|
||||
这么看来使用国密算法加密倒是也没很复杂,但是和国际标准相比也没什么优势。虽然有些地方强制使用那确实没啥办法,但是想要普及肯定是不用想了,另外我自己的东西肯定是不敢用国密,虽然进了标准而且也开放了算法,但是很难说会不会像Dual_EC_DRBG算法那样偷偷插了后门 ~~(虽然我觉得他们应该没这个实力🤣)~~ ,但国际算法有后门我不怕,国内算法有后门那就吓人了🤣。
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user