面壁人浮川 发布的文章 - 浮川的小窝
首页
休闲直播
4K壁纸
统计
更多
关于
留言
归档
搜 索
1
HelloWorld!
147 阅读
2
前端算法整理
138 阅读
3
关于服务器配置反代隐藏端口中遇到的问题
127 阅读
4
emby+alist3+cloudDriver2 emby无法播放网盘资源问题
126 阅读
5
maptalks 一些基础api的再封装(待解耦改装纯方法类)
110 阅读
生活
学习
随笔
吐槽
小秘密
小故事
登录
/
注册
搜 索
SnowLove
累计撰写
69
篇文章
累计收到
5
条评论
首页
栏目
生活
学习
随笔
吐槽
小秘密
小故事
页面
休闲直播
4K壁纸
统计
关于
留言
归档
用户登录
登录
注册
找到
67
篇与
面壁人浮川
相关的结果
2022-09-01
Sub.prototype = Object.create(Vue.prototype) 和 Sub = Object.create(Vue) 的差异理解
不完全相同。Sub.prototype = Object.create(Vue.prototype) 是将 Sub 函数的原型对象设置为一个从 Vue.prototype 对象继承而来的新对象。这意味着 Sub.prototype 对象继承了 Vue.prototype 对象的所有属性和方法,并且任何通过 new Sub() 创建的实例都将继承这些属性和方法。而 Sub = Object.create(Vue) 是将 Sub 对象本身设置为一个从 Vue 对象继承而来的新对象。这意味着 Sub 对象继承了 Vue 对象的所有属性和方法,但是 Sub.prototype 对象仍然是一个空对象,任何通过 new Sub() 创建的实例将不会继承任何 Sub.prototype 对象中的属性和方法。通常在创建一个自定义类时,我们会使用 Sub.prototype = Object.create(Super.prototype) 来设置子类的原型对象,以便继承父类的方法。而使用 Sub = Object.create(Super) 则更适合创建一个新的对象来扩展现有对象的功能,而不是创建一个新的类。下面是针对cerate的验证过程 可能有些絮叨(旺柴)function Vue() `)} this.getAge = function () `)}}Vue.prototype.getProtoName = function () )}Vue.prototype.getProtoAge = function () )}function Sub() // 让Sub构造函数中的prototype等于Vue.prototype/**让Sub构造函数中的prototype等于Vue.prototype等同于Sub.prototype.__proto__ = Vue.prototype因为之前纠结于sub.__propo__ = Sub.prototype实例对象的__proto__指向构造函数的prototype 所以误认为sub.prototype == Sub.__proto__等式也成立此段代码的意义是实现构造函数Sub所声明的所有实例对象 可以通过__proto__属性访问到Vue.prototype中的属性和方法因为sub.__proto__ = Sub.prototype 所以sub.__proto__.__proto__ = Vue.prototype隐式原型链__proto__的作用就是当一个当前对象中没有的属性或方法时通过__proto__属性去当前对象的隐式原型链中查找sub.__proto__指向了构造函数Sub的prototype原型值又因为Object.create所创建的对象的隐式原型链指向了第一个参数对象等同于Sub.prototype = Object.create[这个新创建的对象拥有Vue上所有的属性和方法]注:不包含构造函数中的属性和方法 如果想要继承构造函数中的属性和方法需要使用call或apply方法将构造函数中的属性和方法绑定到新创建的对象上例如:function Sub(name,age) 等同于sub.__proto__= Sub.prototype = Vue.prototypesub.__proto__.__proto__ = Sub.prototype.__proto__ = Vue.prototype */Sub.prototype = Object.create(Vue.prototype, ,})const sub = new Sub()
2022年09月01日
14
0
0
2022-08-04
空手套白狼 哄女朋友的小tips
前阵子闲得无聊 公司又心血来潮准备用python重构代码(一脸问号 二脸懵逼 三问自己不是前端吗),学习使用python做了一个小工具 大神互喷 注释一些 凑活看吧 import json import requests from zhdate import ZhDate import datetime # 登录网址 http://mp.weixin.qq.com/ # 微信测试公众号app_id(需配置) app_id = "xxxxxxx" # 微信测试公众号secret(需配置) secret = "xxxxxxx" # 高德接口天气权限开通(需配置) https://lbs.amap.com/ (参考:https://blog.csdn.net/qq_51055690/article/details/126885110) weather_key = "xxxxxxx" # 微信测试公众号 扫描测试号二维码(需配置) open_id = ['xxxxxxx', 'xxxxxxxx'] # 模板id 模板在下方可参考(需配置) template_id = ["xxxxxxx", "xxxxxxx"] # 模板每日一题详情页 需要配置自己的服务器地址 http://xxx/checkout_examination tepmlate_detail_url = "http://snowlove.synology.me:5131/checkout_examination" # 天气查询城市码 作者山东青岛 码到高德去搜(需配置) city_code = "370200" # 转星期常量 WEEK_LIST = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] # 距春节 每年不一样(需配置) festival_day = [2023, 1, 22] # 在一起的时间点 自己算(需配置) together_days = [2021, 6, 14] # 生日(需配置) 自己算(需配置) birthday = [int(datetime.datetime.today().year) + 1, 1, 5] # 主方法 发送请求 def main(body): # token # print("access_token",access_token,token.json()) access_token = requests.get( url='https://api.weixin.qq.com/cgi-bin/token', params={ "grant_type": "client_credential", "appid": app_id, "secret": secret } ).json()['access_token'] # print("access_token",access_token) r = requests.post( url="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s" % str( access_token), data=json.dumps(body) ) print(json.loads(r.text)) return json.loads(r.text) # 彩虹屁 (刻在模板中加入该项) def get_words(): return '\n' + requests.get("https://api.shadiao.pro/chp").json()['data']['text'] # 获取天气信息 def get_weather(): result = ['', ''] json_data = json.loads(requests.get( url="https://restapi.amap.com/v3/weather/weatherInfo", params={ "city": city_code, "key": weather_key, "extensions": "all" } ).text) print(json_data) if json_data["status"] == "1": for forecast in json_data["forecasts"][0].items(): for casts in forecast: if isinstance(casts, list): for i, cast in enumerate(casts): if i == 0: result[i] = [cast["dayweather"], cast["daytemp"], cast["daywind"]] elif i == 1: result[i] = [cast["dayweather"], cast["daytemp"], cast["nightweather"], cast["nighttemp"]] return result return [['未知', '0', '无'], ['未知', '0', '未知', '0']] # 转农历方法 def get_zh_date(): toady = datetime.date.today() date = [toady.year, toady.month, toady.day] print("date", date) zh_date = ZhDate.from_datetime( datetime.datetime(date[0], date[1], date[2])) print(zh_date.chinese()) return zh_date # 获取距春节的天气 def get_festival(): return (datetime.date(festival_day[0], festival_day[1], festival_day[2]) - datetime.date.today()).days # 获取诗词 def get_poetry_words(): poetry = requests.get("https://v1.jinrishici.com/all.json").json() return "%s \n————《%s》 %s" % (poetry['content'], poetry['origin'], poetry['author']) # 获取备忘录 def get_memorandum(): try: memorandum = requests.get( url="http://snowlove.synology.me:5131/get_memorandum" ).json() print("memorandum", memorandum) if (memorandum['code'] == 0): return memorandum['memorandum'], memorandum['examination'] else: return '暂无' except Exception as e: print("get_memorandum") print(e) return '暂无', '暂无' # 计算生日 避免新一年计算数据问题 def calculate_birthday(): if datetime.date.today().month == 1 and datetime.date.today().day <= 5 and datetime.datetime.now().timestamp() >= datetime.datetime.strptime(str((birthday[0] - 2)) + '-12-31 00:00:00', '%Y-%m-%d %H:%M:%S').timestamp(): birthday[0] = int(datetime.datetime.today().year) # def read_acquaintance(): # with open(filename, 'r', encoding='utf-8') as fileobj: # for line in fileobj: # global acquaintance # acquaintance = int(line.rstrip()) # def write_acquaintance(): # with open(filename, 'w', encoding='utf-8') as fileobj: # fileobj.write(str(acquaintance + 1)) # 模板拼接参数 可添加对应参数 也可注释掉对应参数 def json_params(open_id, temp_id, memorandum, examination): weather = get_weather() th_days = (datetime.date.today( ) - datetime.date(together_days[0], together_days[1], together_days[2])).days # 计算跨年时间 calculate_birthday() bh_days = (datetime.date( birthday[0], birthday[1], birthday[2]) - datetime.date.today()).days bh_days = '有个屁啦~宝宝今天过生日啦' if bh_days == 0 else (str(bh_days) + ' 天') data = { "touser": open_id, "template_id": temp_id, "url": tepmlate_detail_url, "topcolor": "#FF0000", "data": { 'date': { 'value': datetime.datetime.now().strftime('%Y-%m-%d'), 'color': '#228B22' }, 'zhdate': { 'value': get_zh_date().chinese(), 'color': '#73767a' }, 'festival': { 'value': get_festival(), 'color': '#228B22' }, 'week': { 'value': WEEK_LIST[datetime.datetime.now().weekday()], 'color': '#228B22' }, 'weather': { 'value': weather[0][0], 'color': '#FF8C00' }, 'temperature': { 'value': weather[0][2] + '℃', 'color': '#eebe77' }, 'wind': { 'value': weather[0][2] + '风', 'color': '#FF69B4' }, 'dayweather': { 'value': weather[1][0], 'color': '#00BFFF' }, 'daytemp': { 'value': weather[1][3] + '℃', 'color': '#00BFFF' }, 'nightweather': { 'value': weather[1][2], 'color': '#00BFFF' }, 'nighttemp': { 'value': weather[1][3] + '℃', 'color': '#00BFFF' }, 'togetherdays': { 'value': th_days, 'color': '#FF4500' }, 'birthdays': { 'value': bh_days, 'color': '#FFD700' }, # 'caihongpi': { # 情话 # 'value': get_words(), # 'color': '#F56C6C' # }, 'poetry': { # 诗词 'value': get_poetry_words(), 'color': '#00BFFF' }, 'examination': { 'value': examination, 'color': '#228B22' }, 'memorandum': { 'value': memorandum, 'color': '#00BFFF' } } } print(data) return data # 主方法 if __name__ == '__main__': memorandum, examination = get_memorandum() for open_id in open_id: for temp_id in template_id: main(json_params(open_id, temp_id, memorandum, examination)) # get_memorandum() 最终效果放在最后 好久没更新了 这阵子工作太忙了 学到了好多东西也没空写 之后会陆续不上的
2022年08月04日
22
0
0
2022-07-29
百度长文语音生成
Document 语音生成 暂停 继续 let speakText = '',success = 0,audioEle = null function OnInput(e){ const = e.target speakText = value }; function createVideo(){ mainLogText(speakText) }; function pause(){ audioEle.pause() }; function goon(){ audioEle.play() }; // 语音参数 function params(str){ return `lan=zh&ctp=1&cuid=abcdxxx&tok=25.e0970155e0c0c4b833d31ebed0aff7ed.315360000.1910765741.282335-14437940&tex=$&vol=9&per=0&spd=5&pit=5&aue=3` }; // 下载文件 function downLoadBaiduTTSMp3(params,name,delay = 1000,isFile = false){ return new Promise(reslove=>{ const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://tsn.baidu.com/text2audio', true); //也可以使用POST方式,根据接口 xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.responseType = "blob"; //返回类型blob xhr.onload = function () { //定义请求完成的处理函数 const blob = this.response; if(isFile) return reslove(blob) if(blob.size > 0){ const reader = new FileReader(); reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签href reader.onload = function (e) { // 转换完成,创建一个a标签用于下载 const a = document.createElement('a'); a.download = `$.mp3`; a.href = e.target.result; document.body.appendChild(a); a.click(); const timer = setTimeout(()=>{ clearTimeout(timer) reslove(true) },delay) } }else{ console.log("error") } }; xhr.send(params) }) }; function playVideo(e){ return new Promise(async reslove=>{ audioEle = document.getElementById('audio') audioEle.src = window.URL.createObjectURL(e) audioEle.play().then(res=>).catch(err=>{ alert('请手动开始语音播报') }) audioEle.onended = ()=>{ reslove(true) } }) }; // 主方法 async function main(){ const totalNum = 345; const startInd = 56; const arr = new Array(totalNum).fill(null).map((i,index)=>`请$号到闸门前刷身份证考试`); for(let i in arr){ // console.log(arr[i],Number(i) + 1) await downLoadBaiduTTSMp3(params(arr[i]),Number(i) + startInd) } }; // 主方法 下载多个文件 async function mainMultipleAudio(arr){ for(let i in arr){ const currentEle = arr[i] await downLoadBaiduTTSMp3(params(currentEle.text),currentEle.name) } }; // 长文本合成 音频拼接 async function mainLogText(logText){ logText = logText.replace(/\ +/g,"").replace(/[\r\n]/g,"") const arr = [] let time = 0 let chrtNums = 60 for(let i = 0;i
2022年07月29日
67
1
0
2022-03-16
前端算法整理
大数相加相乘 Document num1: num2: let num1 = '',num2 = ''; function OnInput(e){ const = e.target Number(e.target.dataset.type) ? num1 = value : num2 = value } function getResult(type){ // 相加 if(type === 1){ // 计算两个字符串最大长度 const len = Math.max(num1.length,num2.length); // 左侧补零 保持长度相同 let tempNum1 = num1.padStart(len,'0'),tempNum2 = num2.padStart(len,'0'); // 结果数组 let resultArr = [] for(let i = len - 1;i >= 0;i--){ // 计算两个大数本次循环位数相加的总和 加上上次循环可能的进位数字的总和 const bitNum = Number(tempNum1[i]) + Number(tempNum2[i]) + (resultArr[i] || 0) // (进位数最多是两位数) 算取低位 高位 const singleDigit = bitNum % 10,tenDigit = Math.floor(bitNum / 10) console.log("tenDigit",tenDigit) // 数组对应循环的位数替换 进位数的低位 resultArr[i] = singleDigit // 如果不是最后一位 将进位数的高位赋给数组本次循环的前一下标 if(i > 0) { resultArr[i - 1] = tenDigit }else{ // 数组最高位 如果进位数高位为零 不添加 不为零则添加 tenDigit ? resultArr.unshift(tenDigit) : '' } } document.getElementById("RESULT").innerText = resultArr.join('') // 相乘 }else if(type === 2){ // 计算两个字符串长度 const len1 = num1.length,len2 = num2.length; // 结果数组 let resultArr = [] for(let i = len1 - 1;i >= 0;i--){ for(let j = len2 - 1;j >= 0;j--){ // 为了便于理解 这里将难点关系说明 // 1.是从resultArr数组最后一位开始处理的 // 2.首先 for循环是从字符串最后一位开始处理的 // 3.约定resultArr中的数组长度等于乘法运算结果的长度 // 4.for循环中 i+j+1的数值等于本次循环处理字符串下标等于resultArr的下标 i+j的数值等于本次循环处理字符串下标的前一位等于resultArr的下标 // 5.其他见图 const secondDigit = i + j,thridDigit = i + j + 1; // 本次位数相乘加上进位数低位 let product = num1[i] * num2[j] + (resultArr[thridDigit] || 0); resultArr[thridDigit] = product % 10; // 最后一位 if(i === 0 && j === 0){ // 进位数高位加上上次循环可能存在的进位数 const firstDigitNum = Math.floor(product / 10)+ (resultArr[secondDigit] || 0) !== 0 // 如果第一位不为零则添加 if(firstDigitNum) resultArr[secondDigit] = firstDigitNum } } } document.getElementById("RESULT").innerText = resultArr.join('') } } 二维矩阵 Document html,body{ width: 100%; height: 100%; padding: 0; margin: 0; } #xxl-app{ width: 100%; height: 100%; padding: 0; margin: 0; position: relative; } .xxl-span{ display: inline-block; width: 40px; padding: 0px 10px; text-align: center; line-height: 20px; } .xxl-operate-box{ position: absolute; top:60px; right: 30px; } 输入矩阵规模: 输入数字: let num = 0,matrixNum = 10 document.getElementById('xxl-box').innerHTML = innerHtml() function OnInput(e){ const = e.target Number(e.target.dataset.type) ? num = Number(value):matrixNum = Number(value) } function matrix(column){ let str = '' let list = [] for(let i = 0;i { html += `$` if(ind2 === len) html += '' }) html += '' }) return html } function getResult(){ const arr = [...document.getElementsByClassName('xxl-span')] arr.forEach(i=>{ i.setAttribute('style','background:#fff') }) document.getElementById('result').innerHTML = findNum2(num) console.log("123",findNum1(num)[1]) findNum1(num)[1].forEach(i=>{ document.getElementById(i).setAttribute('style','background:#15a5ed') }) } function findNum1(num){ let flag = 0 let ids = [] const arr = matrix(matrixNum) arr.forEach((i,ind)=>{ if(ind === num) ids.push(`r-0-$`) i.forEach(j=>{ if(j === num) { flag = true if(ind === 0) ids.push(`0-$`) else ids.push(`$-$`) } }) }) return [flag ? "有" : "无",ids] } function findNum2(num){ const arr = matrix(matrixNum) const [lastEle,...agrs] = arr.slice(-1)[0].reverse() return num > lastEle ? "无":"有" }
2022年03月16日
138
0
0
2022-03-04
HTTPS原理和通信流程
了解HTTPS之前你还需要了解:加密、证书、签名的原理:对称加密非对称加密数字签名数字证书可逆加密不可逆加密对称加密定义对称加密是指加密和解密的密钥为同一个,用来加密数据的密钥同时也可以用来解密;[tag type="success"]特点[/tag](1)它的特点是加密速度快,使用简单,因为加密解密只需要同一把钥匙就行了;(2)对称加密的破解难度是随着钥匙的大小增加而增加的,钥匙越大就越难破解,但是钥匙越大相应的据解密的时间也会越长;小芳和小明得知了对称加密这种加密方式后他们决定尝试一下,小芳和小明约定好咱们以后问密码的时候统一在每个原来每个数字上加上1;有一天小芳又忘记密码了,发信息给小明问银行卡密码=>。=>小芳:老公银行卡密码是多少。=>小明:234234。这时小芳通过之前和小明的约定,进行计算得到密码 123123。当然这次他们的通话也被黑客所偷听,但是他们对数据进行了加密,所以黑客并不知道它们所说的具体内容是什么当然他们银行卡里的钱也安然无恙。在这个故事中的规则“在原来的每个数字上加1”就相当于对称加密里面的密钥了,加密和解密数据都是使用这一套规则;[tag type="info"]对称加密的问题[/tag](1)双方都必须事先约定好加密规则。(2)密钥的数目难于管理。因为对于每一个合作者都需要使用不同的密钥,很难适应开放互联网中的大量的合作者交流。(3)无法适用于陌生的网络的环境,双方都必须是可信任的才可进行,而在互联网通信过程中我们通信的双方都是互不相识的,如果双方要约定加密规则,那么势必也要通过网络发送加密秘钥,因为网络环境本身就会存在被窃取的可能,我们发送密钥的请求本身又是不安全的。运用对称加密有一个前提就是在发送信息前双方都必须知道加密的规则,但是在互联网的环境下我们每天可能跟不同人发送信息,很多人我们之前根本没认识过,这种情况下我们根本不可能事先就约定好加密规则,那么我们就只能通过信息把加密规则(密钥)发送给对方,然后我们再根据加密规则来加密聊天信息,很显然这肯定是不可取的,不经过加密的数据在网络传输是没有任何安全性可言的,于是就出现了非对称加密;非对称加密定义与对称加密不同,非对称加密的密钥是成对的(公钥和私钥)。私钥由自己安全保管不外泄,而公钥则可以发给网络中的任何人。非对称加密使用这对密钥中的一个进行加密,而解密则需要另一个密钥。根据公钥是无法推导出私钥的;[tag type="success"]特点[/tag](1)比对称加密安全:加密和解密是不同的钥匙,非对称加密的私钥是由自己保管不会外泄的,除了自己没有任何人知道私钥,而对称加密只有一把密钥并且通信双方都要知道密钥,一旦密钥知道的人越多那么安全的风险就越大。(2)更方便可扩展:公钥可以公布在网络中,任何人都可以拿着公钥和你进行通信,而对称加密密钥是不可能公布在网络中的,只能通过私下约定密钥规则。此时小芳和小明发送信息就会是如下流程:1、小明把公钥告诉小芳,私钥由自己保存;2、小芳用小明的公钥加密数据,然后把加密的数据发送给小明。3、小明接收到小芳的消息后用自己的私钥解密消息。4、小明再用自己的私钥加密自己需要回复小芳的信息,然后发送给小芳。5、小芳获取到小明回复的信息后,用小明的公钥解密小明回复过来的信息。[tag type="info"]非对称加密的问题[/tag]虽然非对称加密很安全,但是和对称加密比起来,它的解密速度非常慢,所以通常会用混合加密的方式进行通信,混合加密是用非对称加密的方式交换双方的对称加密秘钥,交换对称加密秘钥之后再用 对称加密的方式进行通信。数字签名定义数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是在使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。[tag type="success"]特点[/tag](1)鉴权公钥加密系统允许任何人在发送信息时使用公钥进行加密,接收信息时使用私钥解密。当然,接收者不可能百分之百确信发送者的真实身份,而只能在密码系统未被破译的情况下才有理由确信。鉴权的重要性在财务数据上表现得尤为突出。举个例子,假设一家银行将指令由它的分行传输到它的中央管理系统,指令的格式是(a,b),其中a是账户的账号,而b是账户的现有金额。这时一位远程客户可以先存入100元,观察传输的结果,然后接二连三的发送格式为(a,b)的指令。这种方法被称作重放攻击。(2)完整性传输数据的双方都总希望确认消息未在传输的过程中被修改。加密使得第三方想要读取数据十分困难,然而第三方仍然能采取可行的方法在传输的过程中修改数据。一个通俗的例子就是同形攻击:回想一下,还是上面的那家银行从它的分行向它的中央管理系统发送格式为(a,b)的指令,其中a是账号,而b是账户中的金额。一个远程客户可以先存100元,然后拦截传输结果,再传输(a,b),这样他就立刻变成百万富翁了。(3)不可抵赖:在密文背景下,抵赖这个词指的是不承认与消息有关的举动(即声称消息来自第三方)。消息的接收方可以通过数字签名来防止所有后续的抵赖行为,因为接收方可以出示签名给别人看来证明信息的来源。这时小芳给小明发送信息需要做4件事:首先把需要发送的信息进行哈希得到信息摘要;=>然后对信息内容和摘要进行签名得到数字签名;=>然后用对称加密秘钥把信息内容和数字签名进行对称加密;=>最后再把对称加密的秘钥进行加密。1、小芳发送信息前首先把需要发送的数据用哈希函数计算出一个哈希值出来得到一个信息摘要(不懂技术的人可以把这个哈希值类比成发送内容里面所有字的笔画的总和,只要内容改变那么这个值就会跟着变),当然这个计算哈希值的过程是不可逆的,无法通过哈希值推导出信息的内容。2、小芳用自己的私钥对信息摘要进行加密得到一个数字签名(因为私钥加密的数据只有公钥才能解密,如果小明用小芳的公钥能解密到正确的数据,那证明此信息必定是由小芳发出)。3、小芳然后用“对称秘钥”对加密信息内容和数字签名进行对称加密。4、最后小芳用小明的公钥对“对称秘钥”进行非对称加密,然后把用加密过后的“对称加密秘钥”,和用对称加密秘钥加密过后的信息内容、数字签名一起发给了小明。当小明接收到小芳的信息后,小明需要做4件事1、当小明收到了小芳的信息后,首先用自己的私钥解密得到对称加密的秘钥。2、然后用对称加密秘钥解密得到 信息信息内容和数字签名。3、然后用小芳的公钥解密数字签名得到信息摘要。4、最后把信息内容进行哈希得到哈希值与解密过后得到的信息摘要进行比对,如果相同则信息没有被篡改过。[tag type="info"]身份确认证的问题[/tag]数字签名解决了信息可能会被篡改的问题,但是还有另外一个问题就是小明如何确定当前给我发信息的人就是小芳呢?黑客也可以伪装成小芳的身份然把小芳的公钥替换成自己的公钥,这样小明无法分辨出来的。数字证书定义*数字证书是指在互联网通讯中标志通讯各方身份信息的一个数字认证,人们可以在网上用它来识别对方的身份。因此数字证书又称为数字标识。数字证书对网络用户在计算机网络交流中的信息和数据等以加密或解密的形式保证了信息和数据的完整性和安全性。*[tag type="success"]特点[/tag](1)安全性。(2)唯一性。(3)便利性。数字证书通常包含以下内容:(1) 证书所有人的公钥; (2) 证书发行者对证书的数字签名; (3) 证书所用的签名算法; (4) 证书发布机构、有效期、所有者的信息等其他信息。 数字证书的验证过程需要用到 CA根证书 和 业务相关证书,根证书 是预装在操作系统中的。在理解数字证书工作原理之前,我们需要先理解这两种证书是怎么生成的:CA根证书的生成![CA证书.jpeg][5] **步骤:** 1. 权威机构利用RSA等算法,生成一对 公钥PK1 / 私钥SK1; 2. 将 公钥PK1 和 证书发布机构、有效期等信息组成一份原始的证书内容,设为 C1; 3. 利用某种摘要算法,计算原始内容 C1 的数字摘要,设为 H1; 4. 用第一步生成的私钥SK1,对摘要H1签名,得到签名内容S1; 5. 将原始内容C1 和 签名内容S1 合在一起,就得到了证书。 根证书安装在操作系统中,我们认为根证书是一定正确的。 业务相关证书的生成![业务证书.jpeg][6] **步骤:** 1. 企业利用RSA等算法,生成一对 公钥PK2 / 私钥SK2; 2. 将 公钥PK2 和 证书其他内容 组成原始证书内容,设为C2[^1],给到权威机构; 3. 权威机构拿到后,利用摘要算法,生成摘要信息 H2[^2]; 4. 权威机构用自己的私钥SK1 (这是关键点),对摘要信息H2[^2] 签名,得到签名内容S2; 5. 将 原始内容C2[^1] 和 签名内容S2 合并到一起,得到证书,交给企业。 [tag type="danger"]区别点在于: **业务申请的证书,在签名时用的私钥是CA机构的私钥。这个私钥是和根证书中的公钥对应的。** [/tag] 最后通讯流程变成下面的情况:1、小芳首先去CA申请一个数字证书;2、小芳把信息加密后+加上签名和数字证书发送给小明;3、小明收到小芳信息后,拿着小芳传过来的数字证书到CA去验证;4、如果查询到对应数字证书信息里的所属人的确为小芳,那么身份真实可以进行通讯;5、然后小明根据数字证书信息生成一个专属于小芳和小明加密方式(这里为对称加密),两个人通过此加密方式进行通讯;消息摘要定义对一份数据,进行一个单向的 Hash 函数,生成一个固定长度的 Hash 值,这个值就是这份数据的摘要,也称为指纹。摘要算法常见的摘要算法有 MD5、SHA-1、SHA-256 [tag type="success"]特点[/tag]对于同一个摘要算法,无论输入的数据是什么,输出都是相同长度的值。 例如 MD5,无论数据有多大,输出总是128位的散列值。摘要算法是单向的,只能根据原始数据计算出它的摘要值,但是不能根据摘要值反算出原始数据。越优秀的摘要算法越难找到Hash碰撞。 虽然长内容生成短摘要是必定会产生碰撞的,但一个优秀的摘要算法很难主动构造出两条数据,使得他们的摘要值相同。消息摘要的用途:可以用于校验数据的完整性。 例如我们在下载文件时,数据源会提供一个文件的MD5。文件下载好之后,我们本地计算出文件的MD5,和数据源提供的MD5做对比,如果相同则文件是完整的。 但独立使用消息摘要时,无法确保数据没有被篡改,因为无法保证从数据源获取的MD5有没有被中途篡改。相比加密算法,摘要算法速度都相对较快。证书链如 CA根证书和服务器证书中间增加一级证书机构,即中间证书,证书的产生和验证原理不变,只是增加一层验证,只要最后能够被任何信任的CA根证书验证合法即可。服务器证书 server.pem 的签发者为中间证书机构 inter,inter 根据证书 inter.pem 验证 server.pem 确实为自己签发的有效证书;中间证书 inter.pem 的签发 CA 为 root,root 根据证书 root.pem 验证 inter.pem 为自己签发的合法证书;客户端内置信任 CA 的 root.pem 证书,因此服务器证书 server.pem 的被信任。服务器证书、中间证书与根证书在一起组合成一条合法的证书链,证书链的验证是自下而上的信任传递的过程。二级证书结构存在的优势:减少根证书结构的管理工作量,可以更高效的进行证书的审核与签发;根证书一般内置在客户端(浏览器或操作系统)中,私钥一般离线存储,一旦私钥泄露,则吊销过程非常困难,无法及时补救;中间证书结构的私钥泄露,则可以快速在线吊销,并重新为用户签发新的证书;证书链四级以内一般不会对 HTTPS 的性能造成明显影响。证书链有以下特点:同一本服务器证书可能存在多条合法的证书链。因为证书的生成和验证基础是公钥和私钥对,如果采用相同的公钥和私钥生成不同的中间证书,针对被签发者而言,该签发机构都是合法的 CA,不同的是中间证书的签发机构不同;不同证书链的层级不一定相同,可能二级、三级或四级证书链。中间证书的签发机构可能是根证书机构也可能是另一个中间证书机构,所以证书链层级不一定相同。 补充:加密分类(可逆加密和不可逆加密)可逆加密可逆加密是指经过加密过后的信息可以通过对应的密钥反向解析还原信息内容,常见的就是我们上面所说的对称加密和非对称加密。常见的对称加密算法:AES、DES、3DES、Blowfish、IDEA、RC4、RC5、RC6常见的非对称加密算法:RSA、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal不可逆加密和可逆加密相反,不可逆加密是指经过加密过后的信息是无法反向解析还原信息内容。比如我们为了保证用户资料的安全,存在数据库的用户密码一般是用不可逆的加密算法进行加密,这样就算系统管理员得到了用户加密过后的密 码,也无法通过解密还原用户的真实密码。常见的不可逆加密算法: MD5、SHA、HMAC这里是分割线...[typing]下面开始正文叙述https原理[/typing]Http协议的不足不验证身份,导致身份可能被伪装HTTP是不会对请求的双方进行身份验证的,服务器不会校验客户端的身份,谁都可以向服务器发送请求,任何人都的请求都会进行响应; 客户端也不会验证响应的数据是否是由自己请求的目标服务器所发出。明文通信,数据可能被窃取HTTP的请求过程中是不会对通信内容进行加密的,在网络中一旦请求或响应的数据被窃取就会导致数据泄漏,造成数据安全问题。无法验证报文的完整性,内容可能被篡改HTTP不会验证数据的前后一致性,一旦数据传输的过程中遭遇中间人的篡改,通信的双发是无法判断自己接收的数据是否和对方发送的数据一致性。SSL/TSL协议的解决方案SSL通常是指SLL和TSL,TSL是在SSL上进行了包装,本质上他们是一样的,通常HTTPS 是HTTP+SSL 或者HTTP+TSL;SSL主要针对HTTP存在的三个问题逐一实现了对应的解决方案。通信加密(解决数据被窃取问题)因为HTTP不对通信内容进行加密处理,所以衍生了SSL加密技术协议,SLL采用混合加密(同时使用非对称加密和对称加密)的方式建立起安全的HTTP通信,经过加密后的内容即使被窃听了,窃听的人也无法解密对应的数据。HTTPS通信流程第一步:客户端向服务端发起请求(1)客户端生成随机数R1 发送给服务端;(2)告诉服务端自己支持哪些加密算法;第二步:服务器向客户端发送数字证书(1)服务端生成随机数R2;(2)从客户端支持的加密算法中选择一种双方都支持的加密算法(此算法用于后面的会话密钥生成);(3)服务端生成把证书、随机数R2、会话密钥生成算法,一同发给客户端;第三步:客户端验证数字证书。 (1)验证证书的可靠性(详细解读)首先你的证书会在https握手过程中被传递到浏览器,浏览器从服务器传来的证书中找到了颁发者,拿着颁发者的值去找你电脑上的证书集(如果你电脑上有的话)又找到了CA的证书(CA证书会在操作系统安装时就安装好,所以每个人电脑上都有根证书)(证书链),使用CA证书中带的公钥来对颁发者证书做验签,此处对验签过程做一下说明:通过证书(此证书是服务器传来的证书)里提供的摘要算法进行对证书内明文数据(上文提到的C21计算获得不可逆hash值,然后使用刚刚查到的CA根证书的公钥对证书(此证书是服务器传来的证书)中的摘要信息H22(CA私钥加密过)进行公钥解密,两相对比(hash值和解密后的H2对比)相等则验签签通过。(2)验证证书合法性,包括证书是否吊销、是否到期、域名是否匹配,通过后则进行后面的流程(3)获得证书的公钥、会话密钥生成算法、随机数R2(4)生成一个随机数R3。(5)根据会话秘钥算法使用R1、R2、R3生成会话秘钥(对称加密)。(6)用服务端证书的公钥加密随机数R3并发送给服务端(非对称加密)。第四步:服务器得到会话密钥(1)服务器用私钥解密客户端发过来的随机数R3(非对称加密)(2)根据会话秘钥算法使用R1、R2、R3生成会话秘钥(对称加密)第五步:客户端与服务端进行加密会话(1)客户端发送加密数据给服务端发送加密数据:客户端加密数据后发送给服务端。(2)服务端响应客户端解密接收数据:服务端用会话密钥解密客户端发送的数据;加密响应数据:用会话密钥把响应的数据加密发送给客户端。(3)客户端解密服务端响应的数据解密数据:客户端用会话密钥解密响应数据;本文皆由网络搜索整理合并知乎 HTTPS原理和通信流程知乎 摘要、签名与数字证书都是什么?简书 HTTPS的请求过程博客园 HTTPS中CA证书的签发及使用过程原始证书内容 ↩摘要信息 ↩
2022年03月04日
103
0
0
1
...
8
9
10
...
14