init: v1.0.0
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package paillier
|
||||
|
||||
// envelope provide hybrid encryption for a user with a remote cryptographic server.
|
||||
// The server has a KEK and the user wants to encrypt a file.
|
||||
// 1. The user generate a random user key ukey
|
||||
// 2. The user use ukey to encrypt the file
|
||||
// 3. The user do the followings to encrypt the ukey with KEK without leaking ukey to the server:
|
||||
// 3-0. The user generate a (temporary or long term) paillier key pair (sk, pk).
|
||||
// 3-1. The user encrypt ukey with paillier encryption: ukeyCipher = PaiEnc(ukey, pk)
|
||||
// 3-2. The server HOMOMORPHICLY encrypt ukey with KEK: ukeyEnvelopeCipher = PaiEnc(SM4Enc(ukey, KEK), pk)
|
||||
// 3-3. The user decrypt ukeyEnvelopeCipher and get ukeyEnvelope = SM4Enc(ukey, KEK)
|
||||
//
|
||||
// The user do the following to decrypt the ukey and then to decrypt the file.
|
||||
// Also without leaking ukey.
|
||||
// 1. The user generate a (temporary or long term) paillier key pair (sk, pk).
|
||||
// 2. User encrypt ukeyEnvelope: ukeyEnvelopeCipher = PaiEnc(ukeyEnvelope, pk)
|
||||
// 3. The server HOMORPHICLY decrypt ukeyEnvelopeCipher: ukeyCipher = PaiEnc(ukey, pk)
|
||||
// 4. The user decrypt ukeyCipher, with ukey.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
"xdx.jelly/xgcl/sm/sm4"
|
||||
)
|
||||
|
||||
// xyzw => 0x0y0z0w
|
||||
var tbl = []byte{0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85}
|
||||
|
||||
type EnvelopeUser struct{}
|
||||
type EnvelopeServer struct{}
|
||||
|
||||
// EncryptUserKey
|
||||
func (EnvelopeUser) EncryptUserKey(ukey []byte, pk *PublicKey) (ukeyCipher *Cipher, err error) {
|
||||
if len(ukey)*8*2 > pk.Bits() {
|
||||
return nil, fmt.Errorf("input key too long, should less than %d bytes", pk.Bits()/8/2)
|
||||
}
|
||||
buf := make([]byte, 0, len(ukey)*2)
|
||||
for _, k := range ukey {
|
||||
buf = append(buf, tbl[k&0xf])
|
||||
buf = append(buf, tbl[k>>4])
|
||||
}
|
||||
return pk.Encrypt(new(big.Int).SetBytes(buf), grand.Reader)
|
||||
}
|
||||
|
||||
func DecryptKey(c *Cipher, keyLength int, priKey *PrivateKey) ([]byte, error) {
|
||||
k, err := priKey.Decrypt(c)
|
||||
_ = err
|
||||
key2 := make([]byte, keyLength*2)
|
||||
k.FillBytes(key2)
|
||||
key := make([]byte, keyLength)
|
||||
for i := 0; i < len(key); i++ {
|
||||
x := key2[2*i]
|
||||
y := key2[2*i+1]
|
||||
n := byte(0)
|
||||
n |= (x >> 0) & 1
|
||||
n |= (x >> 1) & 2
|
||||
n |= (x >> 2) & 4
|
||||
n |= (x >> 3) & 8
|
||||
key[i] = n
|
||||
|
||||
n = byte(0)
|
||||
n |= (y >> 0) & 1
|
||||
n |= (y >> 1) & 2
|
||||
n |= (y >> 2) & 4
|
||||
n |= (y >> 3) & 8
|
||||
key[i] |= (n << 4)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func GenEnvelope(c0 *Cipher, kek []byte, pubkey *PublicKey) ([]byte, *Cipher, error) {
|
||||
iv := grand.GetRandom(16)
|
||||
c1, err := sm4.EncryptECB(nil, kek, iv) // c1 = sm4.Enc(iv)
|
||||
c2, err := EncryptUserKey(c1, pubkey) // c2 = PaiEnc(sm4.Enc(iv))
|
||||
c2.HomomorphicAdd(c2, c0, pubkey) // c2 = PaiEnc(sm4.Enc(iv) ^ key)
|
||||
|
||||
_ = err
|
||||
return iv, c2, nil
|
||||
}
|
||||
|
||||
func DecryptEnvelope(c *Cipher, prikey *PrivateKey) ([]byte, error) {
|
||||
k, err := prikey.Decrypt(c)
|
||||
_ = err
|
||||
key2 := make([]byte, 32)
|
||||
k.FillBytes(key2)
|
||||
key := make([]byte, 16)
|
||||
for i := 0; i < 16; i++ {
|
||||
x := key2[2*i]
|
||||
y := key2[2*i+1]
|
||||
n := byte(0)
|
||||
n |= (x >> 0) & 1
|
||||
n |= (x >> 1) & 2
|
||||
n |= (x >> 2) & 4
|
||||
n |= (x >> 3) & 8
|
||||
key[i] = n
|
||||
|
||||
n = byte(0)
|
||||
n |= (y >> 0) & 1
|
||||
n |= (y >> 1) & 2
|
||||
n |= (y >> 2) & 4
|
||||
n |= (y >> 3) & 8
|
||||
key[i] |= (n << 4)
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
Reference in New Issue
Block a user