你的Electron应用做了代码签名吗?

435 阅读6分钟

在数字化高速发展的今天,软件安全变得越来越受到重视。特别是对于开发人员来说,保证软件的安全性不仅关乎用户体验,更是企业声誉的象征。今天,我们来讲讲代码签名——一种能够提高软件安全性的重要手段。随着Electron框架的流行,越来越多的桌面应用选择了这一平台,那么你的Electron应用做了代码签名吗?

代码签名是什么

0fb5f2616e5477aacd067841722d0aff.png

代码签名是一种数字签名的形式,主要用于确认软件发布者的身份和保证软件自发布以来未被篡改过。通过为软件或电子文档附加一个数字签名,可以确保接收者(用户)能验证发布者的身份以及软件的完整性。

如果软件未进行代码签名,那么它在下载或运行时很可能会被操作系统视为不安全的,弹出警告信息,影响用户体验。未签名的软件很难证明来源的可靠性和完整性,容易被恶意软件或病毒替换,从而给用户造成潜在的安全风险。

Foxmail20240614092233.png

代码签名主要是针对以下几类文件进行签名:

  1. 可执行文件:包括各种应用程序、程序安装包、驱动程序等。对可执行文件进行签名可以确保文件的完整性和来源可信度,以防止文件在传输或运行过程中被篡改或恶意修改。
  2. 动态链接库(DLL) :DLL文件是一种通用的库文件格式,用于存储代码和数据,被多个程序共享。签名DLL文件可以确保程序在加载和运行DLL时不会受到未经授权的更改。
  3. 安装程序:安装程序(如Setup.exe等)用于安装和部署应用程序到用户计算机上。对安装程序进行签名可以增加用户对软件来源的信任,确保软件的安全性。
  4. 代码文件:包括各种编程语言的源代码文件(如JavaScript、Java、C++等),对这些文件进行签名可以确保代码的完整性和安全性,防止恶意篡改或未经授权的修改。
  5. 配置文件:诸如配置文件、元数据文件等,这些文件通常包含应用程序的设置信息和其他关键参数。对这些文件进行签名可以防止配置信息被篡改导致应用程序运行异常。

通过对这些关键文件进行签名,开发者可以确保软件的完整性和安全性,用户也能更加信任软件的来源和运行环境,提升整体的软件可信度。

代码签名的类型

代码签名证书需要由权威可信的 CA 机构签发,目前全球大大小小的占有一定市场份额的代码签名证书签发机构(CA)大概有十多个。

这些代码签名证书在中国主要通过环度网信等这样的合作伙伴来提供售前售后服务,我们以环度网信上正在提供的几个主流代码签名证书品牌为例,主要有 DigiCert,GlobalSign,Sectigo,Entrust,Certum 这几个品牌。

ssl证书主要分为两类:OV和EV

OV(Organization Validation)代码签名证书与EV(Extended Validation)代码签名证书主要区别在于验证严格度、信任级别、颁发机构要求及获取过程的复杂性。OV证书提供企业级身份验证,验证过程涉及申请者的组织信息,确保软件发布者是一家经过合法注册并运行的实体。而EV证书的验证标准更为严格,除了包括所有OV证书的身份验证步骤之外,还需要额外的组织信息和法律存在性的验证,因此获取EV证书通常要耗费更长的时间并且成本更高。发布者使用EV代码签名证书时,用户在下载和安装软件时会获得更高级别的安全提示,提升了用户对软件的信任度dGtkkP1689301800.jpg

由于我们一般都不会跟签名机构直接购买,而是跟签名机构的合作二三级渠道购买,所以中间会有较大的浮动空间,目前看一般都是EV的都是3-5k左右一年。

通常情况下,EV代码签名证书的价格要高于OV代码签名证书。二期渠道商还会提供一些Pro版本,Pro版本功能上其实是一样的,只是时间周期的差异,因为签名机构一般都是在美国,购买Pro版本,可以直接从国内拿货,大城市可以隔天到,如果不是Pro版本,可能就得半个月左右了。

如何进行代码签名

8249016d21794a59885ed03243ebf031.jpeg

要进行代码签名,需要如下几步:

1、证书:进行代码签名之前,肯定需要先购买证书,拿到证书后一般会是一个证书文件(.pfx),或者是证书的usb。

2、签名工具:一般使用signtool,如果是用的electron-builder,其内置了该工具,一些EV的证书如果用signtool可能会需要手动输入密码,如果想接入自动化流程,可以使用渠道商封装的签名工具,一般都是基于signtool的二次开发。

3、electron的签名时机:构建完成之后执行

electron-builder的配置如下:

win: {
    "target": ["nsis"],
    "timeStampServer": "http://timestamp.digicert.com",
    "icon": iconPath,
    "artifactName": "61drawlive_student_${version}.${ext}",
    "verifyUpdateCodeSignature": false,
    "requestedExecutionLevel": "highestAvailable",
    "sign": path.join(rootPath, "./script/winSign.js"),
    "signDlls": true,
},

winSign脚本如下,基于EV证书

const { execSync } = require('child_process')
const path = require('path')
const rootPath = path.resolve(__dirname, '../')
async function sign(config) {
  console.log(JSON.stringify(config))
  execSync(`${path.join(rootPath, './script/wosigncodecmd.exe')} sign /tp 证书指纹 /p ukey密码 /hide /c /dig sha256 /tr ${config.options.timeStampServer} /file ${config.path}`)
}
module.exports = sign

这是一个使用渠道商的签名例子,可以根据自己情况做调整

winSign脚本,基于OV证书

const { execSync } = require('child_process')
const envConfig = require('dotenv').config().parsed
async function sign (config) {
  console.log(JSON.stringify(config))
  if (config.options.signingHashAlgorithms.includes('sha1')) {
    execSync(`signtool sign /v /debug /f ./src/nsis/certificate/cer-sha1.pfx /p ${envConfig.WIN_CSC_PASSWORD} /t ${config.options.timeStampServer} ${config.path}`)
  }
  execSync(`signtool sign /as /v /debug /f ./src/nsis/certificate/globalsignEV.pfx /fd SHA256 /p ${envConfig.WIN_CSC_PASSWORD} /tr ${config.options.rfc3161TimeStampServer} /td SHA256 ${config.path}`)
}
module.exports = sign

注意,代码证书跟网页的证书都是一样有有效期的。不过过期不会影响已经签名的文件,已经签名的文件会带上签名的时间戳,只要跟签名里的符合要求即可。

最后,如果你还在犹豫要不要为你的Electron应用进行代码签名,希望本文的内容能够给你一些启发。记住,代码签名不仅可以增加应用的可信度,还可以保证用户的安全。赶紧行动起来,让你的应用更加出色吧!愿你的Electron应用风调雨顺,代码签名顺利!

END