github.com/tommi2day/gomodules@v1.13.2-0.20240423190010-b7d55d252a27/pwlib/openssl_test.go (about) 1 package pwlib 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "encoding/base64" 7 "fmt" 8 "os" 9 "os/exec" 10 "strings" 11 "testing" 12 13 "github.com/tommi2day/gomodules/common" 14 15 "github.com/tommi2day/gomodules/test" 16 17 openssl "github.com/Luzifer/go-openssl/v4" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 ) 21 22 const ( 23 plaintext = "hallowelt" 24 //nolint gosec 25 passphrase = "z4yH36a6zerhfE5427ZV" 26 plainfile = ` 27 # Testfile 28 !default:defuser2:failure 29 !default:testuser:default 30 test:testuser:testpass 31 testdp:testuser:xxx:yyy 32 !default:defuser2:default 33 !default:testuser:failure 34 !default:defuser:default 35 ` 36 ) 37 38 // var digest = openssl.BytesToKeySHA256 39 40 func TestEncryptToDecrypt(t *testing.T) { 41 o := openssl.New() 42 enc, err := o.EncryptBytes(passphrase, []byte(plaintext), SSLDigest) 43 if err != nil { 44 t.Fatalf("Test errored at encrypt: %s", err) 45 } 46 47 dec, err := o.DecryptBytes(passphrase, enc, SSLDigest) 48 if err != nil { 49 t.Fatalf("Test errored at decrypt: %s", err) 50 } 51 52 if string(dec) != plaintext { 53 t.Errorf("Decrypted text did not match input.") 54 } 55 } 56 57 func TestPublicEncryptString(t *testing.T) { 58 app := "test_encrypt_String" 59 testdata := test.TestData 60 pc := NewConfig(app, testdata, testdata, "Test", typeGO) 61 62 err := os.Chdir(test.TestDir) 63 require.NoErrorf(t, err, "ChDir failed") 64 _, _, err = GenRsaKey(pc.PubKeyFile, pc.PrivateKeyFile, pc.KeyPass) 65 require.NoErrorf(t, err, "Prepare Key failed:%s", err) 66 67 crypted, err := PublicEncryptString(plaintext, pc.PubKeyFile) 68 // run 69 t.Run("default Encrypt String", func(t *testing.T) { 70 assert.NoErrorf(t, err, "Encryption failed: %s", err) 71 assert.NotEmpty(t, crypted, "Crypted String empty") 72 }) 73 74 t.Run("default Decrypt String", func(t *testing.T) { 75 actual, err := PrivateDecryptString(crypted, pc.PrivateKeyFile, pc.KeyPass) 76 expected := plaintext 77 assert.NoErrorf(t, err, "Decryption failed: %s", err) 78 assert.NotEmpty(t, actual) 79 assert.Equalf(t, expected, actual, "Data Mismatch exp:%s,act:%s", expected, actual) 80 }) 81 } 82 83 func TestOpensslCompString(t *testing.T) { 84 // echo -n "$plain"|openssl rsautl -encrypt -pkcs -inkey $PUBLICKEYFILE -pubin |base64 85 // echo -n "$CRYPTED"|base64 -d |openssl rsautl -decrypt -inkey ${PRIVATEKEYFILE} -passin pass:$KEYPASS 86 87 var cmdout bytes.Buffer 88 var cmderr bytes.Buffer 89 test.Testinit(t) 90 app := "test_openssl_string" 91 testdata := test.TestData 92 93 // set env 94 pc := NewConfig(app, testdata, testdata, "Test", typeOpenssl) 95 err := os.Chdir(test.TestDir) 96 require.NoErrorf(t, err, "ChDir failed") 97 98 // prepare keys 99 _, _, err = GenRsaKey(pc.PubKeyFile, pc.PrivateKeyFile, pc.KeyPass) 100 require.NoErrorf(t, err, "Prepare Key failed:%s", err) 101 t.Run("Encrypt_Openssl-Decrypt_String", func(t *testing.T) { 102 // encrypt using openssl os cmd 103 cmdArgs := []string{ 104 "openssl", "rsautl", 105 "-inkey", pc.PubKeyFile, 106 "-pubin", 107 "-pkcs", 108 "-encrypt", 109 } 110 // nolint gosec 111 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 112 t.Logf("CMD: %v", cmdArgs) 113 cmdout.Reset() 114 cmderr.Reset() 115 cmd.Stdout = &cmdout 116 cmd.Stderr = &cmderr 117 cmd.Stdin = strings.NewReader(plaintext) 118 if err := cmd.Run(); err != nil { 119 t.Fatalf("Running openssl CLI failed: %v (%s)", err, cmderr.String()) 120 } 121 // encode base64 122 crypted := base64.StdEncoding.EncodeToString(cmdout.Bytes()) 123 124 // decode openssl encoded string with go functions 125 actual, err := PrivateDecryptString(crypted, pc.PrivateKeyFile, pc.KeyPass) 126 if err != nil { 127 t.Fatalf("Decryprion failed: %v", err) 128 } 129 // compare 130 expected := plaintext 131 assert.NotEmpty(t, actual) 132 assert.Equalf(t, expected, actual, "Data Mismatch exp:%s,act:%s", expected, actual) 133 }) 134 135 t.Run("Encrypt_String-OpenSSL_decrypt", func(t *testing.T) { 136 // encode string with go functions 137 crypted, err := PublicEncryptString(plaintext, pc.PubKeyFile) 138 if err != nil { 139 t.Fatalf("Encryprion failed: %v", err) 140 } 141 t.Logf("B64: %s", crypted) 142 // revert base64 encoding 143 b64dec, err := base64.StdEncoding.DecodeString(crypted) 144 if err != nil { 145 t.Fatalf("decode base64 failed: %v", err) 146 } 147 148 // decode crypted string in bin format using openssl os cmd 149 cmdArgs := []string{ 150 "openssl", "rsautl", 151 "-inkey", pc.PrivateKeyFile, 152 "-pkcs", 153 "-decrypt", 154 "-passin", fmt.Sprintf("pass:%s", pc.KeyPass), 155 } 156 // nolint gosec 157 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 158 t.Logf("CMD: %v", cmdArgs) 159 cmdout.Reset() 160 cmderr.Reset() 161 cmd.Stdout = &cmdout 162 cmd.Stderr = &cmderr 163 cmd.Stdin = bytes.NewReader(b64dec) 164 expected := plaintext 165 if err := cmd.Run(); err != nil { 166 t.Fatalf("Running openssl CLI failed: %v (%s)", err, cmderr.String()) 167 } 168 actual := cmdout.String() 169 // compare 170 assert.NotEmpty(t, actual) 171 assert.Equalf(t, expected, actual, "Data Mismatch exp:%s,act:%s", expected, actual) 172 }) 173 } 174 175 func TestOpensslFile(t *testing.T) { 176 var cmdout bytes.Buffer 177 var cmderr bytes.Buffer 178 test.Testinit(t) 179 app := "test_openssl_file" 180 testdata := test.TestDir + "/testdata" 181 // set env 182 pc := NewConfig(app, testdata, testdata, app, typeOpenssl) 183 err := os.Chdir(test.TestDir) 184 require.NoErrorf(t, err, "ChDir failed") 185 filename := pc.PlainTextFile 186 _ = os.Remove(filename) 187 //nolint gosec 188 err = os.WriteFile(filename, []byte(plainfile), 0644) 189 require.NoErrorf(t, err, "Create testdata failed") 190 191 // prepare keys 192 _, _, err = GenRsaKey(pc.PubKeyFile, pc.PrivateKeyFile, pc.KeyPass) 193 require.NoErrorf(t, err, "Prepare Key failed:%s", err) 194 // run 195 t.Run("default Encrypt File", func(t *testing.T) { 196 err := PubEncryptFileSSL(pc.PlainTextFile, pc.CryptedFile, pc.PubKeyFile, pc.SessionPassFile) 197 assert.NoErrorf(t, err, "Encryption failed: %s", err) 198 assert.FileExists(t, pc.CryptedFile) 199 }) 200 t.Run("default Decrypt File", func(t *testing.T) { 201 plaintxt, err := common.ReadFileToString(pc.PlainTextFile) 202 require.NoErrorf(t, err, "PlainTextfile %s not readable:%s", err) 203 expected := len(plaintxt) 204 content, err := PrivateDecryptFileSSL(pc.CryptedFile, pc.PrivateKeyFile, pc.KeyPass, pc.SessionPassFile) 205 assert.NoErrorf(t, err, "Decryption failed: %s", err) 206 assert.NotEmpty(t, content) 207 actual := len(content) 208 assert.Equalf(t, expected, actual, "Lines misamtch exp:%d,act:%d", expected, actual) 209 }) 210 t.Run("Encrypt_Openssl-Decrypt_Api", func(t *testing.T) { 211 const rb = 16 212 var actual, crypted string 213 // create session key 214 random := make([]byte, rb) 215 _, err = rand.Read(random) 216 if err != nil { 217 t.Fatalf("Cannot generate session key:%s", err) 218 } 219 sessionKey := base64.StdEncoding.EncodeToString(random) 220 t.Logf("Create Random SessionKeyin %s: %s", pc.SessionPassFile, sessionKey) 221 222 // encrypt session key and save to file 223 // echo -n sessionKey |openssl rsautl -encrypt -pkcs -inkey PubKeyFile -pubin |openssl enc -base64 -out SessionPassFile 224 crypted, err = PublicEncryptString(sessionKey, pc.PubKeyFile) 225 if err != nil { 226 t.Fatalf("Encrypting Keyfile failed: %v", err) 227 } 228 //nolint gosec 229 err = os.WriteFile(pc.SessionPassFile, []byte(crypted), 0644) 230 if err != nil { 231 t.Fatalf("Cannot write session Key file %s:%v", pc.SessionPassFile, err) 232 } 233 234 // encrypt using openssl cmd 235 cmdArgs := []string{ 236 "openssl", "enc", "-e", 237 "-aes-256-cbc", 238 "-base64", 239 "-pass", fmt.Sprintf("pass:%s", sessionKey), 240 "-md", "sha256", 241 "-in", pc.PlainTextFile, 242 "-out", pc.CryptedFile, 243 } 244 // nolint gosec 245 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 246 t.Logf("CMD: %v", cmdArgs) 247 cmdout.Reset() 248 cmderr.Reset() 249 cmd.Stdout = &cmdout 250 cmd.Stderr = &cmderr 251 if err = cmd.Run(); err != nil { 252 t.Fatalf("Running openssl CLI failed: %v (%s)", err, cmderr.String()) 253 } 254 255 // decrypt openssl encoded data using API 256 actual, err = PrivateDecryptFileSSL(pc.CryptedFile, pc.PrivateKeyFile, pc.KeyPass, pc.SessionPassFile) 257 258 // compare 259 expected := plainfile 260 assert.NotEmpty(t, actual) 261 assert.Equalf(t, expected, actual, "Data Mismatch exp:%s,act:%s", expected, actual) 262 }) 263 t.Run("Encrypt_API-Decrypt_openssl", func(t *testing.T) { 264 // encrypt using api 265 err := PubEncryptFileSSL(pc.PlainTextFile, pc.CryptedFile, pc.PubKeyFile, pc.SessionPassFile) 266 assert.NoErrorf(t, err, "Cannot Encrypt using API:%s", err) 267 if err != nil { 268 t.Fatalf("Cannot Encrypt using API:%s", err) 269 } 270 271 // verify witch openssl cmd 272 // read session pass file 273 //nolint gosec 274 data, err := os.ReadFile(pc.SessionPassFile) 275 if err != nil { 276 t.Fatalf("Cannot Read SessionPassFile %s:%v", pc.SessionPassFile, err) 277 } 278 cryptedKey := string(data) 279 // revert base64 encoding 280 b64dec, err := base64.StdEncoding.DecodeString(cryptedKey) 281 if err != nil { 282 t.Fatalf("decode base64 failed: %v", err) 283 } 284 285 // decode crypted string in bin format using openssl os cmd 286 cmdArgs := []string{ 287 "openssl", "rsautl", 288 "-inkey", pc.PrivateKeyFile, 289 "-pkcs", 290 "-decrypt", 291 "-passin", fmt.Sprintf("pass:%s", pc.KeyPass), 292 } 293 // nolint gosec 294 cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) 295 t.Logf("CMD: %v", cmdArgs) 296 cmdout.Reset() 297 cmderr.Reset() 298 cmd.Stdout = &cmdout 299 cmd.Stderr = &cmderr 300 cmd.Stdin = bytes.NewReader(b64dec) 301 if err := cmd.Run(); err != nil { 302 t.Fatalf("Running openssl CLI failed: %v (%s)", err, cmderr.String()) 303 } 304 sessionKey := cmdout.String() 305 t.Logf("SessionKey: %s", sessionKey) 306 307 // decrypt using openssl cmd, must use -base64 -A for singleline base64 string 308 cmdArgs = []string{ 309 "openssl", "enc", "-d", 310 "-aes-256-cbc", 311 "-base64", 312 "-A", 313 "-pass", fmt.Sprintf("pass:%s", sessionKey), 314 "-md", "sha256", 315 "-in", pc.CryptedFile, 316 } 317 // nolint gosec 318 cmd = exec.Command(cmdArgs[0], cmdArgs[1:]...) 319 t.Logf("CMD: %v", cmdArgs) 320 cmdout.Reset() 321 cmderr.Reset() 322 cmd.Stdout = &cmdout 323 cmd.Stderr = &cmderr 324 if err := cmd.Run(); err != nil { 325 t.Fatalf("Running openssl CLI failed: %v (%s)", err, cmderr.String()) 326 } 327 328 actual := cmdout.String() 329 // compare 330 expected := plainfile 331 assert.NotEmpty(t, actual) 332 assert.Equalf(t, expected, actual, "Data Mismatch exp:%s,act:%s", expected, actual) 333 }) 334 }