文章
121
标签
24
分类
11
首页
时间线
标签
分类
说说
更多
相册
书单
电影
游戏
友情链接
关于
M-finder
2023年9月流水账
返回首页
首页
时间线
标签
分类
说说
更多
相册
书单
电影
游戏
友情链接
关于
2023年9月流水账
发表于
2023-09-30
|
更新于
2026-03-16
|
闲言赘语
|
总字数:
66
|
阅读时长:
1分钟
|
浏览量:
最近沉迷 swift,忙里抽闲做了几个菜单栏小工具,外加一个小工具合集,高产似母猪,啊哈哈哈……
看看后续能不能再多做几个,到时候搞个开发者账号发到苹果商店去。
文章作者:
m-finder
文章链接:
https://m-finder.alon.wang/2023-09-23-swift/
版权声明:
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议。转载请注明来源
M-finder
!
闲言赘语
上一篇
为你的 Laravel 应用添加一个基于 Swoole 的 WebSocket 服务
做了一个基于 Swoole 的 WebSocket 扩展包,可以用来做实时状态推送,或者自定义消息处理实现 im,有需要的可以看看: [giorgio-socket] 使用方法安装安装扩展包 1composer require wu/giorgio-socket 发布配置文件 1php artisan vendor:publish --provider="GiorgioSocket\Providers\SocketServiceProvider" 运行 Socket 服务 1php artisan socket:start 注意事项 可以通过实现 GiorgioSocket\Services\Handlers\Interfaces 下的接口类来自定义自己的业务逻辑。 如果要从服务端发送消息,这里有两种方式: 第一种,借助 Laravel HTTP 客户端 123456Route::get('/socket', function () { \Illuminate\Support\Facades\Http::asForm()->post('http://127.0.0.1:9501', [ 'to' => 2, 'message' => 'server message', ]);}); 第二种:借助 Laravel Listener,需要将 .env 文件中的 QUEUE_CONNECTION 配置修改为 redis 或其他异步队列。配置更改后,运行以下命令:php-artisan queue:work --queue=socket-listener监听队列,然后按以下代码调用 event: 123Route::any('socket', function (Request $request){ \GiorgioSocket\Events\SocketEvent::dispatch($request->get('to'), $request->get('message'));}); 如果你正在使用 laravel/breeze 扩展包,并且使用了 Blade 模板,可以将以下代码粘贴到 dashboard.blade.php 中进行快速测试: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111@auth <div class="py-12"> <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg"> <div class="grid grid-cols-1 md:grid-cols-2"> <div class="p-6" id="server-message"> messages:<br/> </div> <div class="p-6"> <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="from">from</label> <input class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" value="{{ auth()->user()->getKey() }}" id="from"> <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="to">to</label> <input class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" value="" id="to"> <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="message">message</label> <textarea class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" id="message"></textarea> <input class="inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 mt-3" type="button" id="submit" value="submit"> </div> </div> </div> </div> </div> <script type="text/javascript"> let heartBeatTimer = 0; let socket = connectWebSocket(); function startHeartbeat(interval) { interval = interval || 30; heartBeatTimer = setInterval(function () { sendMessage(null, "heart_beat"); }, interval * 1000); } function stopHeartbeat() { clearInterval(heartBeatTimer); } function connectWebSocket() { const wsServer = 'ws://127.0.0.1:9501'; const socket = new WebSocket(wsServer); let userId = document.getElementById('from').value; socket.onopen = function (evt) { let data = { user_id: userId, type: 'connect' }; console.log('open', data) socket.send(JSON.stringify(data)); }; socket.onmessage = function (evt) { console.log('get message from server: ' + evt.data); if (evt.data !== 'heart_beat') { let data = JSON.parse(evt.data); let message = document.getElementById("server-message") message.innerHTML += data.user_name + ': ' + data.data + '<br/>' } }; socket.onerror = function (evt) { console.log(evt); }; socket.onclose = function () { let data = { user_id: userId, type: 'close' }; socket.send(JSON.stringify(data)); }; return socket; } function sendMessage(to, message) { if (socket != null && socket.readyState === WebSocket.OPEN) { if (message !== 'heart_beat') { let messageBox = document.getElementById("server-message") messageBox.innerHTML += 'me: ' + message + '<br/>' } let from = document.getElementById("from") socket.send(JSON.stringify({ user_id: from.value, user_name: '{{ auth()->user()->name }}', to: to, type: 'message', data: message, })); console.log("webSocket send message:" + JSON.stringify({ user_id: from.value, user_name: '{{ auth()->user()->name }}', to: to, type: 'message', data: message, })); } else { console.log("webSocket closed"); } } let button = document.getElementById("submit"); button.addEventListener('click', function () { let message = document.getElementById("message"); let to = document.getElementById("to"); sendMessage(to.value, message.value) }); </script>@endauth 如有任何疑问,欢迎提交 [issue]
下一篇
php 国密 sm2 sm3 sm4 完整测试类
应用范围及描述 算法类型 国密算法 应用范围及描述 对称加密 SM1 128位数据加密,算法不公开,仅以IP核的形式存在于芯片中。智能IC卡、智能密码钥匙、加密卡、加密机。 非对称加密 SM2 被用来替换RSA算法。常用于身份认证,数据签名,密码交换,256位椭圆曲线。 完整性运算 SM3 256位数据摘要计算,相当于SHA256,数字签名及验证、消息认证码生成及验证、随机数生成 对称加密 SM4 128位数据加密,相当于AES(128) 相关代码php sm2 sm3 sm4 完整测试类,可拖入 laravel unit test 模块运行。基于扩展包 [ lpilp/guomi ] , sm2 与兴业银行有部分区别,sm4 已互通,未做招行验证。 sm2 密钥长度一般为 128 或 130 位,部分使用压缩密钥长度为 66,也就是将密钥分成 x、y,y是偶数就是02,y是奇数就是03,通过 x 可以算出 y。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290<?phpnamespace Tests\Unit;use FG\ASN1\ASNObject;use FG\ASN1\Exception\ParserException;use Mdanter\Ecc\Crypto\Signature\Signature;use Mdanter\Ecc\Serializer\Signature\DerSignatureSerializer;use PHPUnit\Framework\TestCase;use Rtgm\sm\RtSm2;use Rtgm\sm\RtSm3;use Rtgm\sm\RtSm4;/** * 国密加密测试 * sm4 已与兴业银行调通 */class GmTest extends TestCase{ /** * 获取 sm2 * @return RtSm2 */ private function getSm2(): RtSm2 { return new RtSm2('base64'); } /** * 获取 sm3 * @return RtSm3 */ private function getSm3(): RtSm3 { return new RtSm3(); } /** * 获取 sm4 * @return RtSm4 */ private function getSm4(): RtSm4 { $privateKey = $this->getSm4PrivateKey(); return new RtSm4($privateKey); } /** * 获取 16进制 sm2 密钥 * 生成于工具站 https://www.lzltool.com/SM2 base64格式 * @return string */ private function getSm2PrivateKey(): string { return bin2hex(base64_decode('L8TbMByc+rQmKECWMBjnDQHrXrExqZKdl5S6sBbP07M=')); } /** * 获取 16进制 sm2 公钥 * 生成于工具站 https://www.lzltool.com/SM2 base64格式 * @return string */ private function getSm2PublicKey(): string { return bin2hex(base64_decode('BCxc4cDX1OQEpCD8O7wzPhTOljYg0uzfsMAEanCvYgBIj966+i5pgjwyIOtFSNWLWjoDzLmMJP9nf2cVmiH+aYI=')); } /** * sm2 数据格式化 * @param $dec * @return string */ private function sm2FormatHex($dec): string { $hex = gmp_strval(gmp_init($dec, 10), 16); $len = strlen($hex); if ($len == 64) { return $hex; } return $len < 64 ? str_pad($hex, 64, "0", STR_PAD_LEFT) : substr($hex, $len - 64, 64); } /** * 获取 16位 密钥 * @return bool|string */ private function getSm4PrivateKey(): bool|string { return base64_decode('NmQzZDQ2YTcxMmRjNGE0NQ=='); } /** * 获取待加密字符串 * @return string */ private function getDataStr(): string { return '{"bankCardNo":"6212028190240439021","certNo":"41052619700925136X","userName":"南瓜"}'; } /** * 拼接 sm2 待加密字符串 * @return bool|string */ private function getSm2SignStr(): bool|string { $params = json_decode($this->getDataStr(), true); $signStr = ''; if ($params != null) { ksort($params); foreach ($params as $k => $v) { $signStr .= "{$k}={$v}&"; } } return substr($signStr, 0, strlen($signStr) - 1); } public function test_sm2_sign() { $sm2 = $this->getSm2(); $signStr = $this->getSm2SignStr(); // 加密 $sign = $sm2->doSign($signStr, $this->getSm2PrivateKey()); $encryptStr = base64_decode($sign); try { $a = ASNObject::fromBinary($encryptStr)->getChildren(); } catch (ParserException $e) { $this->fail('加密失败: ' . $e->getMessage()); } $aa = $this->sm2FormatHex($a[0]->getContent()); $bb = $this->sm2FormatHex($a[1]->getContent()); $encryptStr = base64_encode(hex2bin($aa . $bb)); $this->assertNotEmpty($encryptStr); return $encryptStr; } public function test_sm2_verify_sign() { $sm2 = $this->getSm2(); $encryptSignStr = bin2hex(base64_decode($this->test_sm2_sign())); echo 'sm2 sign str: ', $encryptSignStr, PHP_EOL; $r = substr($encryptSignStr, 0, 64); $s = substr($encryptSignStr, 64, 64); $r = gmp_init($r, 16); $s = gmp_init($s, 16); $signature = new Signature($r, $s); $serializer = new DerSignatureSerializer(); $sign = base64_encode($serializer->serialize($signature)); $boolean = $sm2->verifySign($this->getSm2SignStr(), $sign, $this->getSm2PublicKey()) ?? false; echo $boolean ? 'sm2 验签通过' : 'sm2 验签失败', PHP_EOL; $this->assertTrue($boolean); } public function test_sm2_encrypt() { $sm2 = $this->getSm2(); // 压缩公钥 $key = $this->decompressPublicKey('0315edd9126410e9b94b83ee2bcdfeebe9166e84d7aad1b9d16fa923995d28e81f'); $encrypt = $sm2->doEncrypt($this->getDataStr(), $key); $this->assertNotEmpty($encrypt); return $encrypt; } public function test_sm2_decrypt() { $sm2 = $this->getSm2(); $encrypt = $this->test_sm2_encrypt(); $privateKey = 'bf5e3e47e5392a8cdba8e3f854db2d3f5e2c536235303a02898b58d085a8246a'; echo 'sm2 encrypt str: ', $encrypt, PHP_EOL; $decryptStr = $sm2->doDecrypt($encrypt, $privateKey); echo 'sm2 decrypt str: ', $decryptStr, PHP_EOL; $this->assertNotEmpty($decryptStr); $this->assertTrue($decryptStr === $this->getDataStr()); } /** * 获取未压缩公钥 * @param $compressedKey * @return string|null */ function decompressPublicKey($compressedKey): ?string { // 获取压缩标志和X坐标 $flag = substr($compressedKey, 0, 2); $x = substr($compressedKey, 2); // 将16进制字符串转换为大整数 $p = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16); $a = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16); $b = gmp_init('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16); $gx = gmp_init('32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1711D7AFB1B8B4E16', 16); $gy = gmp_init('BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0', 16); $n = gmp_init('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16); // 计算Y坐标 $x = gmp_init($x, 16); $alpha = gmp_powm($x, 3, $p); $beta = gmp_add(gmp_mod(gmp_mul($a, $x), $p), $b); $y2 = gmp_mod(gmp_add($alpha, $beta), $p); $y = gmp_powm($y2, gmp_div_q(gmp_add($p, 1), 4), $p); if ($flag == "02") { // 如果压缩标志为 02,则Y坐标为偶数 if (gmp_strval(gmp_mod($y, 2)) != "0") { $y = gmp_sub($p, $y); } return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT); } if ($flag == "03") { // 如果压缩标志为 03,则Y坐标为奇数 if (gmp_strval(gmp_mod($y, 2)) != "1") { $y = gmp_sub($p, $y); } return "04" . gmp_strval($x, 16) . str_pad(gmp_strval($y, 16), 64, "0", STR_PAD_LEFT); } return null; } public function test_sm3() { $sm3 = $this->getSm3(); $signStr = $sm3->digest($this->getDataStr()); echo 'sm3 sign str: ', $signStr, PHP_EOL; $this->assertNotEmpty($signStr); } /** * 测试 byteArr to string * @return string */ public function test_sm4_iv() { $byteArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; $iv = call_user_func_array('pack', array_merge(['C*'], $byteArr)); $this->assertTrue(base64_encode($iv) === 'AAAAAAAAAAAAAAAAAAAAAA=='); return base64_encode($iv); } public function test_sm4_encrypt() { try { $iv = $this->test_sm4_iv(); $sm4 = $this->getSm4(); $encryptJsonStr = $sm4->encrypt($this->getDataStr(), 'sm4', base64_decode($iv)); } catch (\Exception $e) { $this->fail('加密异常:' . $e->getMessage()); } $encryptJsonStr = base64_encode(hex2bin($encryptJsonStr)); $this->assertNotEmpty($encryptJsonStr); return $encryptJsonStr; } public function test_sm4_decrypt() { try { $sm4 = $this->getSm4(); $encryptJsonStr = $this->test_sm4_encrypt(); echo "sm4 encrypt str: " . $encryptJsonStr, PHP_EOL; $decryptJsonStr = $sm4->decrypt(bin2hex(base64_decode($encryptJsonStr)), 'sm4', base64_decode($this->test_sm4_iv())); } catch (\Exception $e) { $this->fail('解密异常:' . $e->getMessage()); } echo "sm4 decrypt str: " . $decryptJsonStr, PHP_EOL; echo $decryptJsonStr === $this->getDataStr() ? 'sm4 数据一致' : 'sm4 数据不一致', PHP_EOL; $this->assertNotEmpty($decryptJsonStr); }}
相关推荐
2021-04-08
少年,留下你的键帽吧!
今天干了一件有点伤感,但是挺有意思的事情。虽然是个流水账,但是我觉得有必要记录一下。 我跟要离职的 阿龙同学 换了一个键帽。 我想,如果把这个做法一直延续下去,每离职一个关系不错的小伙伴就相互交换一个键帽,那最后这把键盘也就非常有意义了,对吧。 😓看我这油光铮亮的空格…… 网络一线牵,珍惜这段缘。 祝愿阿龙的工作越来越好!
2022-01-01
2022 年计划清单
减肥 上半年软考-系统分析师,2月中旬报名,5月下旬考试 下半年软考-系统架构设计师 ,8月中上旬报名,11月下旬考试 没有其他了。 – 2021-12-31 2022-08-06已经瘦了差不多20斤吧,还在继续努力系分的软考g了,因为疫情一直拖,直到昨天看到公告说取消了开始冲刺下半年架构,干巴得💪 2022-11-05多次报名初次参考,可惜论文写的有点惨不忍睹,只能明年再接再厉。
2025-06-09
php、java 和我
前几天 java 30 了,今天看到 php 也 30 了。 我就不一样了,我 30 多了。
2019-07-30
哈!
很久很久以前,有只自认为自己是狼的哈士奇,叫大哈。 后来,他找到了一个让他愿意把骨头让出来的人。 祝他做一只幸福的哈士奇,每天都有骨头吃。
2018-02-15
新年快乐,祝大家狗年旺旺旺
一晚上的火车,再加上3个小时的大巴,总算是在年前赶回了家。 看着周围熟悉的环境,听着亲切万分的乡音,瞬间觉得,这一路的折腾也没什么大不了的。 可能这就是“家”所赋予“年”的特殊力量吧。 忐忐忑忑的本命年,终于在今天画上了句号。 回头想想,又特么一如既往地穷了一年。不过,这些在今天看来,似乎都不太重要了,重要的是老子畏畏缩缩的过了本命年,明天又可以继续开始浪~ 哈哈哈哈哈…… 2017”鸡”将结束,2018”犬”力以赴!! 祝大家新年快乐,狗年好合,哦不,狗年大吉,狗年旺旺旺!
2023-01-01
2023 年计划清单
继续减肥 装修&办小红本 下半年软考-系统架构设计师 ,8月中上旬报名,11月下旬考试 我倒要看看这个证我能考几年
m-finder
happy coding
文章
121
标签
24
分类
11
Follow Me
最新文章
2026 年计划清单
2026-03-16
2025 年计划清单
2025-12-15
飞牛 NAS + Tailscale 组网踩坑实录
2025-12-10
Mac 菜单栏多合一工具 FancyTool 更新啦!
2025-09-12
Mac 菜单栏多合一工具自荐:FancyTool
2025-08-25