iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 26
1
Security

看完眼眶濕濕的App開發者慘烈對抗險惡資安環境血與淚的控訴!系列 第 26

Day 26. 非對稱式加密演算法 - 橢圓曲線密碼 ECC (實戰篇)

大家好,我是羊小咩

前面介紹過 ECC 的觀念篇,今天來介紹 ECC 使用,由於ECC實現難度高,且 ECDH(金鑰交換),ECIES (ECC加密) ECDSA(數位簽章演算法),都要分別實現,因此要支援全部的方法,和多種曲線套件真的很少

比起 RSA 來說 ECC 套件跟資料真的少很多,但相信ECC 的發展,會越來越多

這篇就當做是拋磚塊,看能不能引出更棒想法及作法

iOS / Swift

在 Swift ECC 可以使套件 BlueECC / CryptorECC

https://github.com/Kitura/BlueECC

支援 curves

  • prime256v1
  • secp384r1
  • secp521r1

另外也可以使用原生函式庫 Apple CryptoKit。需要iOS13+

詳細可見官方 CryptoKit 文件

安裝掸ˇ

Cocoapods

pod "BlueECC"

引用

import CryptorECC

建立金鑰 - 私鑰

let eccPrivateKey1 = try! ECPrivateKey.make(for: .prime256v1)
//let eccPrivateKey1 = try! ECPrivateKey.make(for: .secp384r1)
let privateKeyPEM1 = eccPrivateKey1.pemString //私鑰 PEM格式
print(privateKeyPEM)
-----BEGIN EC PRIVATE KEY-----
 MHcCAQEEID7535QYt+y/ObP202MBBkbxCWmXuMbK/twNQOnf+uehoAoGCCqGSM49
 AwEHoUQDQgAEJnMKq9TviSt2NRH1UV1t6AGDotMA0zmhQDxy605BzxcAhYJpBaTd
 JjKERrhK+v4l6LgCm5Y7UnFvmNXHe3Qe2A==
 -----END EC PRIVATE KEY-----

載入已有金鑰

With a PEM string
let privateKey = "-----BEGIN EC PRIVATE KEY----- ........ -----END EC PRIVATE KEY-----"
let eccPrivateKey = try! ECPrivateKey(key: privateKey)
print(eccPrivateKey.pemString)

計算公鑰

let eccPublicKey = try! eccPrivateKey.extractPublicKey()
print(eccPublicKey.pemString)
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEJnMKq9TviSt2NRH1UV1t6AGDotMA
0zmhQDxy605BzxcAhYJpBaTdJjKERrhK+v4l6LgCm5Y7UnFvmNXHe3Qe2A==
-----END PUBLIC KEY-----

使用公鑰加密

let plainText = "Clear Text"
let encryptedData = try! plainText.encrypt(with: eccPublicKey)
print(encryptedData.base64EncodedString())

使用私鑰解密

let decryptedData = try! encryptedData.decrypt(with: eccPrivateKey)
print(String(data: decryptedData, encoding: .utf8))

NodeJS / ES6

NodeJS ECC 相關的套件主要是 ECDH ECDSA居多

ECIES 幾乎沒幾個,原因是官方系統函式庫根本不支援ECIES 崩╰(〒皿〒)╯潰

詳情可見Node 官方Crypto 文件 https://nodejs.org/dist/latest-v14.x/docs/api/crypto.html

因此有神人就寫了一個套件 eccrypto 可支援ECDH ECDSA 以及 ECIES

https://github.com/bitchan/eccrypto

功能算完善,可惜支援曲線和演算法太少

Only secp256k1 curve, only SHA-512 (KDF), HMAC-SHA-256 (HMAC) and AES-256-CBC for ECIES

安裝

npm install eccrypto

引用

var eccrypto = require("eccrypto");

建立金鑰 - 私鑰

var privateKey = eccrypto.generatePrivate();

載入已有金鑰

var asn = require("asn1.js");
var der_b64 = pri_str.match(/-----$([^]+)^-----/m)[1];
var der = Buffer(der_b64, "base64");
var Key = asn.define("Key", function() {
  this.seq().obj(
    this.key("_n").int(),
    this.key("priv").octstr()
  );
});
var privateKey = Key.decode(der, "der");

計算公鑰

var publicKey = eccrypto.getPublic(privateKey);

使用公鑰加密

let textData = Buffer.from("Message"))
eccrypto.encrypt(publicKey, textData).then(function(encrypted) {
  console.log(encrypted.toString())
});

使用私鑰解密

eccrypto.decrypt(privateKey, encrypted).then(function(plaintext) {
    console.log("Message :", plaintext.toString());
  });

其他 ECC 套件推薦

sslcrypto 是在 Python 簡易使用 AES, ECIES ECDSA 套件

sslcrypto 支援度就非常的強大,可以用橋接方式在其他語言實現

https://github.com/imachug/sslcrypto

ECIES

The following curves are supported:

  • secp112r1, secp112r2
  • secp128r1, secp128r2
  • secp160k1, secp160r1, secp160r2
  • secp192k1, prime192v1
  • secp224k1, secp224r1
  • secp256k1, prime256v1
  • secp384r1
  • secp521r1

同場加映 OpenSSL Command

建立私鑰

// p-256
openssl ecparam -name prime256v1 -genkey -noout -out key.pem
// p-384
openssl ecparam -name secp384r1 -genkey -noout -out key.pem
// p-521
openssl ecparam -name secp521r1 -genkey -noout -out key.pem

計算公鑰

openssl ec -in key.pem -pubout -out public.pem

參考資料

https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations

https://github.com/Kitura/BlueECC

https://www.npmjs.com/package/eccrypto

https://github.com/imachug/sslcrypto

https://developer.apple.com/documentation/cryptokit

https://nodejs.org/dist/latest-v14.x/docs/api/crypto.html


上一篇
Day 25. 非對稱式加密演算法 - RSA (實戰篇)
下一篇
Day 27. 混血的最萌 - 混合加密系統(hybrid cryptosystem)
系列文
看完眼眶濕濕的App開發者慘烈對抗險惡資安環境血與淚的控訴!31

尚未有邦友留言

立即登入留言