-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
R22627
authored and
R22627
committed
Sep 6, 2023
1 parent
87f1f4d
commit 63b8a72
Showing
4 changed files
with
216 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"crypto/sha256" | ||
"crypto/sha512" | ||
"crypto/x509" | ||
"encoding/pem" | ||
"errors" | ||
) | ||
|
||
// GenRsaKey generates an PKCS#1 RSA keypair of the given bit size in PEM format. | ||
func GenRsaKey(bits int) (prvkey, pubkey []byte, err error) { | ||
// Generates private key. | ||
privateKey, err := rsa.GenerateKey(rand.Reader, bits) | ||
if err != nil { | ||
return | ||
} | ||
derStream := x509.MarshalPKCS1PrivateKey(privateKey) | ||
block := &pem.Block{ | ||
Type: "RSA PRIVATE KEY", | ||
Bytes: derStream, | ||
} | ||
prvkey = pem.EncodeToMemory(block) | ||
|
||
// Generates public key from private key. | ||
publicKey := &privateKey.PublicKey | ||
derPkix, err := x509.MarshalPKIXPublicKey(publicKey) | ||
if err != nil { | ||
return | ||
} | ||
block = &pem.Block{ | ||
Type: "RSA PUBLIC KEY", | ||
Bytes: derPkix, | ||
} | ||
pubkey = pem.EncodeToMemory(block) | ||
return | ||
} | ||
|
||
// RsaEncrypt encrypts data using rsa public key. | ||
func RsaEncrypt(pubkey, data []byte) ([]byte, error) { | ||
block, _ := pem.Decode(pubkey) | ||
if block == nil { | ||
return nil, errors.New("decode public key error") | ||
} | ||
pub, err := x509.ParsePKIXPublicKey(block.Bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return rsa.EncryptPKCS1v15(rand.Reader, pub.(*rsa.PublicKey), data) | ||
} | ||
|
||
// RsaDecrypt decrypts data using rsa private key. | ||
func RsaDecrypt(prvkey, cipher []byte) ([]byte, error) { | ||
block, _ := pem.Decode(prvkey) | ||
if block == nil { | ||
return nil, errors.New("decode private key error") | ||
} | ||
prv, err := x509.ParsePKCS1PrivateKey(block.Bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return rsa.DecryptPKCS1v15(rand.Reader, prv, cipher) | ||
} | ||
|
||
// RsaSign signs using private key in PEM format. | ||
func RsaSign(prvkey []byte, hash crypto.Hash, data []byte) ([]byte, error) { | ||
block, _ := pem.Decode(prvkey) | ||
if block == nil { | ||
return nil, errors.New("decode private key error") | ||
} | ||
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// MD5 and SHA1 are not supported as they are not secure. | ||
var hashed []byte | ||
switch hash { | ||
case crypto.SHA224: | ||
h := sha256.Sum224(data) | ||
hashed = h[:] | ||
case crypto.SHA256: | ||
h := sha256.Sum256(data) | ||
hashed = h[:] | ||
case crypto.SHA384: | ||
h := sha512.Sum384(data) | ||
hashed = h[:] | ||
case crypto.SHA512: | ||
h := sha512.Sum512(data) | ||
hashed = h[:] | ||
} | ||
return rsa.SignPKCS1v15(rand.Reader, privateKey, hash, hashed) | ||
} | ||
|
||
// RsaVerifySign verifies signature using public key in PEM format. | ||
func RsaVerifySign(pubkey []byte, hash crypto.Hash, data, sig []byte) error { | ||
block, _ := pem.Decode(pubkey) | ||
if block == nil { | ||
return errors.New("decode public key error") | ||
} | ||
pub, err := x509.ParsePKIXPublicKey(block.Bytes) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// SHA1 and MD5 are not supported as they are not secure. | ||
var hashed []byte | ||
switch hash { | ||
case crypto.SHA224: | ||
h := sha256.Sum224(data) | ||
hashed = h[:] | ||
case crypto.SHA256: | ||
h := sha256.Sum256(data) | ||
hashed = h[:] | ||
case crypto.SHA384: | ||
h := sha512.Sum384(data) | ||
hashed = h[:] | ||
case crypto.SHA512: | ||
h := sha512.Sum512(data) | ||
hashed = h[:] | ||
} | ||
return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), hash, hashed, sig) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package crypto | ||
|
||
import ( | ||
"crypto" | ||
"testing" | ||
|
||
"github.com/dablelv/go-huge-util/internal" | ||
) | ||
|
||
func TestRsaEncryptDecrypt(t *testing.T) { | ||
assert := internal.NewAssert(t, "RsaEncryptDecrypt") | ||
|
||
data := []byte("foo") | ||
|
||
// Encrypt and decrypt data using 2048 bits length key. | ||
prvkey, pubkey, err := GenRsaKey(2048) | ||
assert.IsNil(err) | ||
|
||
// Encrypt data. | ||
cipher, err := RsaEncrypt(pubkey, data) | ||
assert.IsNil(err) | ||
assert.Equal(2048/8, len(cipher)) | ||
|
||
// Decrypt data. | ||
plain, err := RsaDecrypt(prvkey, cipher) | ||
assert.IsNil(err) | ||
assert.Equal(data, plain) | ||
|
||
// Encrypt and decrypt data using 4096 bits length key. | ||
prvkey, pubkey, err = GenRsaKey(4096) | ||
assert.IsNil(err) | ||
|
||
// Encrypt data. | ||
cipher, err = RsaEncrypt(pubkey, data) | ||
assert.IsNil(err) | ||
assert.Equal(4096/8, len(cipher)) | ||
|
||
// Decrypt data. | ||
plain, err = RsaDecrypt(prvkey, cipher) | ||
assert.IsNil(err) | ||
assert.Equal(data, plain) | ||
|
||
// Encrypt and decrypt data using 8192 bits length key. | ||
prvkey, pubkey, err = GenRsaKey(8192) | ||
assert.IsNil(err) | ||
|
||
// Encrypt data. | ||
cipher, err = RsaEncrypt(pubkey, data) | ||
assert.IsNil(err) | ||
assert.Equal(8192/8, len(cipher)) | ||
|
||
// Decrypt data. | ||
plain, err = RsaDecrypt(prvkey, cipher) | ||
assert.IsNil(err) | ||
assert.Equal(data, plain) | ||
} | ||
|
||
func TestRsaSignAndVerify(t *testing.T) { | ||
assert := internal.NewAssert(t, "RsaSignAndVerify") | ||
|
||
msg := []byte("foo") | ||
prvkey, pubkey, err := GenRsaKey(2048) | ||
assert.IsNil(err) | ||
|
||
// Using SHA256 to hash msg and then use rsa private key to sign. | ||
sig, err := RsaSign(prvkey, crypto.SHA256, msg) | ||
assert.IsNil(err) | ||
assert.Equal(2048/8, len(sig)) | ||
|
||
// Using public key to verify signature. | ||
err = RsaVerifySign(pubkey, crypto.SHA256, msg, sig) | ||
assert.IsNil(err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
module github.com/dablelv/go-huge-util | ||
module github.com/dablelv/cyan | ||
|
||
go 1.19 | ||
|
||
|