私钥加密公钥解密,称之为签名。签名的目的是验证消息发送者的身份,杜绝伪造。因为私钥只有消息发送者有,所以只有发送者才能制造消息。因为是公钥,谁都可以解密,所以签名不是为了保密,而是为了验证身份。
公钥加密私钥解密,称之为加密,也就是把明文变为加密文,只有接收者才能解读内容。原理很简单,需要通讯的时候接收者把公钥发给发送者(不怕泄漏,要不怎么叫公钥),发送者用公钥加密,把秘文发给接受者,半路上被截获了也没用,因为要解密需要私钥,而私钥只有接收者有。
主要有两个流程签名和签名校验
签名流程1.输入密码,生成秘钥,生成一个ECDSA-P256密钥对(一个公钥一个私钥),公钥以PKIX格式保存。如下所示
— — -BEGIN PUBLIC KEY — — - MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEroVS8KdYXp5SSI5YDwwQymSByQAM 7MDgk9po3wpp/hHZAzCLsu+j3axrJJ5nMet9tqX1eH8yk21G626Z8lrkQA== — — -END PUBLIC KEY — — -
2.私钥的key以PKCS8格式经过输入的密码加密后以PEM文件保存,如下所示
— — -BEGIN ENCRYPTED COSIGN PRIVATE KEY — — - eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6 OCwicCI6MX0sInNhbHQiOiJrSGE5Q1ozTzdFSUtubTNWbnh2WVdvY2k2RWNhcEFD ZE9NbWxXRTV4YTY0PSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94 Iiwibm9uY2UiOiJXcUxtcHZJaml5SklmWGt4YnJaUStXUzg3dFlBeUY1SiJ9LCJj aXBoZXJ0ZXh0IjoiR1BXMjB3Q1l6d09PeUt2aDMwUzFudnFmLyt0ZVBYSmtXM3F3 TzFEMmwrdk1GQ3o2MHFKU1I1ZTF1UTRlcWxUaTdmdjNkYVlLcUJyNlltcnFGV1Yx cnlDQ2gwMXhzOGFsd3BxSS85U0pTTjNVVnZXODkxc1hESHc2SEo5dkNIZHdNUldv WHVVTUdZb0FDd2dyUWZiK3lGNnFOYkQ3dEkrdExlWjRSb1owa3R3Q24zQVErd2hj U0h4ZjYvQmFNVUwzK1gyK3dnNENVM1dtb0E9PSJ9 — — -END ENCRYPTED COSIGN PRIVATE KEY — — -
3.对我们镜像的OCI格式的镜像manifest(描述了镜像的元数据metadata,层layers,配置)的sha256-hash进行签名(该值就是我们下载镜像时候可以使用的xx@sha256值),而不是我们直接以tar保存的manifest,该格式是一种用于镜像分发和存储时使用的格式,可以参考附录学习,如下所示
root@ubuntu:/opt/clash# docker manifest inspect le0zh0u/revshell:v1
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 2227,
"digest": "sha256:2caf248e52e074f3c378d0ba0beae73ffca96bb1e2f5f66ee0163284b266018e"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 28566292,
"digest": "sha256:e0b25ef516347a097d75f8aea6bc0f42a4e8e70b057e84d85098d51f96d458f9"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 35799571,
"digest": "sha256:bc4a0ae6c2a5d4cd1dc65d5f3d911a6fd686e5865d29cde902794b5bf9e0970a"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 40923432,
"digest": "sha256:cabf4367ad37b41c0ccfc4c581735d47066f46d7016b22e5a17c6f2e4df0a1ce"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 426,
"digest": "sha256:5a83e814d5bab8208249b3a534f4891369d6737d7d58690a3dd4ab6444382399"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 832092,
"digest": "sha256:e69f171010dcf660812baaa356d4e2c6eeb08500d1512780c4cfc45ef3398c10"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 795639,
"digest": "sha256:4f061c233cef716785d467acf4f368fedaf0f8ae2277abae15198a02b631c743"
},
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 15386242,
"digest": "sha256:8d156b958e11a9d42c751d1723dddf4ee7edb702b12db2db0b22168a3af96d21"
}
]
}
4.这里介绍一个格式,RedHat简单签名(simply-sign)格式,我们会把镜像相关的内容保存为如下 JSON,包含了镜像的digest和其来源,之后我们对其做签名
{"critical":{"identity":{"docker-reference":"index.docker.io/le0zh0u/revshell"},"image":{"docker-manifest-digest":"sha256:dc41ac611bccde6d9334d67a2156574d80fa335da29f0171ad4499dc53ec1fe6"},"type":"cosign container image signature"},"optional":null}
6.将签名经过base64加密后,使用OCI规定的Image manifests格式来推送到仓库进行保存,其中添加了annotation字段放置了我们经过base64加密后的签名,如下所示
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config": {
"mediaType": "application/vnd.oci.image.config.v1+json",
"size": 233,
"digest": "sha256:995b5ca9e5f22ffe011c118134e04807065467276ce06ce507f91028847462ec"
},
"layers": [{
"mediaType": "application/vnd.dev.cosign.simplesigning.v1+json",
"size": 248,
"digest": "sha256:577179080231cb1d834b298224777bcbaedb7ea8f10cdb3b48ceee27ec0a4c17",
"annotations": {
"dev.cosignproject.cosign/signature": "MEUCIQC9DbwZe/ng0UeDTbRyl6X0kQ//2BHSMDELUAbKfa42WQIgQfX4yavBTE0TAQXXhuqfOGV4gmPqg4Sf4z+tT9qSqs0="
}
}]
}
7.成功推送签名到仓库,其名字为sha256-xxxxxxxxx.sig,并且我们可以看到其hash既为我们推送时的镜像manifest
验证1.根据我们镜像去仓库获取我们需要拉取镜像的manifest,得到digest
2.通过镜像名字检索其仓库中的数字签名,既.sig文件
3.通过GET请求获取我们的签名镜像(.sig)的blob,既层内容
GET https://index.docker.io/v2/le0zh0u/revshell/blobs/sha256:577179080231cb1d834b298224777bcbaedb7ea8f10cdb3b48ceee27ec0a4c17
得到签名镜像(.sig)文件的blob,获取其内容如下
{"critical":{"identity":{"docker-reference":"index.docker.io/le0zh0u/revshell"},"image":{"docker-manifest-digest":"sha256:dc41ac611bccde6d9334d67a2156574d80fa335da29f0171ad4499dc53ec1fe6"},"type":"cosign container image signature"},"optional":null}
4.通过签名镜像(.sig)的manifest中的"dev.cosignproject.cosign/signature"获取到我们签名数据
"MEUCIQC9DbwZe/ng0UeDTbRyl6X0kQ//2BHSMDELUAbKfa42WQIgQfX4yavBTE0TAQXXhuqfOGV4gmPqg4Sf4z+tT9qSqs0="
5.base64解密我们的签名镜像(.sig)数据,之后我们对上面的签名层的内容进行签名校验,证明其签名镜像(.sig)内容没有篡改
6.通过一系列验证,证明了签名镜像(.sig)内容没有被篡改,且我们也获取了我们需要拉取镜像的digest,接下来我们会对比签名中的包含的简单签名中的,和我们需要拉取镜像的digest一致,则验证通过。既镜像安全。



