Secure software enclave for storage of sensitive information in memory.

Overview

MemGuard

Software enclave for storage of sensitive information in memory.


This package attempts to reduce the likelihood of sensitive data being exposed when in memory. It aims to support all major operating systems and is written in pure Go.

Features

  • Sensitive data is encrypted and authenticated in memory with XSalsa20Poly1305. The scheme used also defends against cold-boot attacks.
  • Memory allocation bypasses the language runtime by using system calls to query the kernel for resources directly. This avoids interference from the garbage-collector.
  • Buffers that store plaintext data are fortified with guard pages and canary values to detect spurious accesses and overflows.
  • Effort is taken to prevent sensitive data from touching the disk. This includes locking memory to prevent swapping and handling core dumps.
  • Kernel-level immutability is implemented so that attempted modification of protected regions results in an access violation.
  • Multiple endpoints provide session purging and safe termination capabilities as well as signal handling to prevent remnant data being left behind.
  • Side-channel attacks are mitigated against by making sure that the copying and comparison of data is done in constant-time.
  • Accidental memory leaks are mitigated against by harnessing the garbage-collector to automatically destroy containers that have become unreachable.

Some features were inspired by libsodium, so credits to them.

Full documentation and a complete overview of the API can be found here. Interesting and useful code samples can be found within the examples subpackage.

Installation

$ go get github.com/awnumar/memguard

API is experimental and may have unstable changes. You should pin a version. [modules]

Contributing

  • Submitting program samples to ./examples.
  • Reporting bugs, vulnerabilities, and any difficulties in using the API.
  • Writing useful security and crypto libraries that utilise memguard.
  • Implementing kernel-specific/cpu-specific protections.
  • Submitting performance improvements.

Issues are for reporting bugs and for discussion on proposals. Pull requests should be made against master.

Issues
  • [Suggestions] Can the API be improved?

    [Suggestions] Can the API be improved?

    As we move closer to v1.0.0, do you have any suggestions for improvements to the API?

    I've used the library myself in my own projects, so primarily that's the only indication I have of the suitability, ease-of-use, and just general quality of the API.

    So, to those of you that use memguard (or not), add a comment with your opinions or suggestions.

    help wanted 
    opened by awnumar 24
  • Memguard Panics After Creating 15 Objects

    Memguard Panics After Creating 15 Objects

    Program:

    package main
    
    import (
    	"fmt"
    	"github.com/libeclipse/memguard"
    )
    
    func main() {
    	for i := 0; i < 100; i++ {
    		key := []byte("123456768901234567890123456789012")
    		safeKey, err := memguard.NewFromBytes(key, true)
    		if err != nil {
    			panic(err.Error())
    		}
    		fmt.Printf("%v: %v\n", i, safeKey)
    	}
    }
    

    Output on a CentOS Linux release 7.3.1611 VM:

    0: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    1: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    2: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    3: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    4: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    5: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    6: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    7: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    8: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    9: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    10: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    11: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    12: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    13: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    14: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    15: &{{0 0} [49 50 51 52 53 54 55 54 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50 51 52 53 54 55 56 57 48 49 50] true false}
    panic: memguard.memcall.Lock(): could not acquire lock on 0x7f7711a67000 [Err: cannot allocate memory]
    
    goroutine 1 [running]:
    github.com/libeclipse/memguard/memcall.Lock(0x7f7711a67000, 0x1000, 0x2000)
    	~/go/src/github.com/libeclipse/memguard/memcall/memcall_unix.go:18 +0x16c
    github.com/libeclipse/memguard.New(0x21, 0x4cd800, 0x21, 0x30, 0x21)
    	~/go/src/github.com/libeclipse/memguard/memguard.go:78 +0xf6
    github.com/libeclipse/memguard.NewFromBytes(0xc420010bd0, 0x21, 0x30, 0xc420010b01, 0x21, 0x30, 0x0)
    	~/go/src/github.com/libeclipse/memguard/memguard.go:113 +0x34
    main.main()
    	try.go:11 +0x8a
    

    It happens on every run on this host. I get the same results on a CentOS release 6.9 (Final) VM. It does not fail on my Mac.

    documentation 
    opened by theory 24
  • Maybe get rid of most package level variables

    Maybe get rid of most package level variables

    Maybe I should have thought this through a bit more, but it seems to me that there is too much package level variables. I think that prevents memguard from being used by multiple dependencies of a Go program. For example; consider a program "package a" that depends on memguard/core and also on "package b", which in turn depends on memguard/core. Suppose both "a" and "b" try to set core.Interval, then there is a data race as it is not known which store to core.Interval happened last and which will affect the memguard funcs.

    proposal 
    opened by nsajko 16
  • Multiple changes

    Multiple changes

    • Refactoring of functionality into core package.
    • Addition of Enclave objects which store encrypted data.
    • Rewrite of signals handling. Should make implementing further data catching much easier.
    • Rewrite and simplification of the API.
    • Addition of examples package.
    • Patched data races in interrupt handling functionality.
    • Conceal mapped memory from core dumps on OpenBSD.
    • Additional functionality added such as safe panicking.
    • Disable core dumps by default. Users that want them can enable themselves.
    • Use local entropy pool for fast random bytes reading.
    • Use a variable sized canary value with 32 <= len(canary) <= ~pagesize.
    • Other optimisations and improvements.
    • ...
    patch feature api-change performance security needs-review 
    opened by awnumar 14
  • What's possible reason .Bytes() returns an empty slice on LockedBuffer from enclave.Open() ?

    What's possible reason .Bytes() returns an empty slice on LockedBuffer from enclave.Open() ?

    We encountered an infrequent problem at runtime in one of Ubuntu docker containers:

    panic: runtime error: slice bounds out of range [:32] with capacity 0
    goroutine 147009 [running]:
    github.com/xxx/secretsclient.EncryptMapData(0xc03ca81c80, 0x4, 0xc0209ba1b0, 0xc0004d5200, 0x45, 0x5e, 0x0, 0x0)
    	/go/pkg/mod/github.com/xxx/[email protected]/encrypt.go:125 +0x1fae
    ...
    

    The code segment around encrypt.go:125 is (with an added line # and comments)

    (119)	keyIVBuf, err := encKeyIV.Open()  // encKeyIV was from keyiv.Seal() with keyiv.Size() == KeyIVSIZE(48)
    	if err != nil {
    		return err
    	}
    	defer keyIVBuf.Destroy()
    
    (125)	block, err := aes.NewCipher(keyIVBuf.Bytes()[:cKeySize])  // cKeySize = 32
    	if err != nil {
    		return err
    	}
    

    Couldn't figure out what went wrong... would a low memlock ulimit possibly cause this? Thanks. (we do have ulimit setting

    / # cat /etc/security/limits.conf
    * soft memlock 512000
    * hard memlock 1024000
    

    Somehow the ulimit command still shows the default (this would encounter problems quickly for us):

    / # ulimit -l
    64
    

    so a little puzzled here too.) Appreciate your help!!

    Additional info: version github.com/awnumar/memguard v0.22.2 OS: Ubuntu 16.04 docker image Go 1.13

    We are also seeing the following error now in one of the docker instances (same instance as above):

    panic: runtime error: index out of range [0] with length 0
    goroutine 6911 [running]:
    github.com/awnumar/memguard/core.(*Coffer).View(0xc00001ec90, 0x0, 0x0, 0x0)
    	/go/pkg/mod/github.com/awnumar/[email protected]/core/coffer.go:112 +0x207
    github.com/awnumar/memguard/core.Open(0xc00979aa20, 0x661f81, 0xc00000ab40, 0x0)
    	/go/pkg/mod/github.com/awnumar/[email protected]/core/enclave.go:101 +0x60
    github.com/awnumar/memguard.(*Enclave).Open(0xc009482150, 0xc034b6d278, 0x4, 0xc009482150)
    	/go/pkg/mod/github.com/awnumar/[email protected]/enclave.go:43 +0x32
    github.com/xxx/secretsclient.EncryptMapData(0xc034b6d278, 0x4, 0xc02fd7cea0, 0xc00016d6c0, 0x16, 0x1c, 0x0, 0x0)
    	/go/pkg/mod/github.com/xxx/[email protected]/encrypt.go:119 +0x9d
    ...
    
    bug duplicate question 
    opened by ns-gzhang 12
  • Support custom randomness source

    Support custom randomness source

    Is your feature request related to a problem? Please describe. When testing cryptographic systems it's always useful to be able to have a predictable source of randomness so you can support test vectors. For NewImmutableRandom, NewMutableRandom, FillRandomBytes, FillRandomBytesAt it would be nice to be able to provide predictable randomness during a test phase.

    Describe the solution you'd like One way of solving the problem would be to have a way of temporarily setting a rand Reader for the package temporarily. Another solution would be that each LockedBuffer has an io.Reader associated with it, that can be set (although that doesn't help for NewImmutableRandom and NewMutableRandom. Another solution would be to add functions that take a Reader for the randomness source.

    Describe alternatives you've considered I don't really have any good alternatives to how to solve this.

    tests proposal 
    opened by olabini 10
  • Use finalizers to prevent leaks

    Use finalizers to prevent leaks

    As suggested in https://www.reddit.com/r/golang/comments/6s84ky/memory_security_in_go/dlcmzp3/

    Some cosmetic/ux changes may be needed. LockedBuffers() was removed to allow implementing automatic destruction. This shouldn't be much of a problem since I can't think of any good use cases outside of DeleteAll().

    feature 
    opened by CAFxX 10
  • proposal: protect data with noaccess until it is read

    proposal: protect data with noaccess until it is read

    Is your feature request related to a problem? Please describe. Currently the guard pages use noaccess protection, but the inner region (canary + data) is still readable. This leaves the inner region vulnerable to memory scans (have verified this locally).

    Describe the solution you'd like It would be nice to have an option to make the inner region always be set to noaccess and only make it read-only when it needs to be read. Making this a default behavior would likely require a breaking API change. This is also similar to what's described in https://download.libsodium.org/doc/memory_management#guarded-heap-allocations in the sodium_mprotect_noaccess related info (specifically, This function can be used to make confidential data inaccessible except when actually needed for a specific operation.).

    We have Java and C# implementations that are very similar to your project and libsodium (we only came across your project when our Go implementation was started). The approach we've taken is:

    • accepting a lambda/function from the user that operates on the data
    • call mprotect with readonly before the lambda invocation and then mprotect with noaccess after the lambda completes
    • we use a lock and access counter to minimize the mprotect readonly and noaccess system calls to only be done when needed (readonly after 1st access, noaccess after last caller exits)

    You can refer to how we've implemented this in https://github.com/godaddy/asherah/blob/4ead9ca1803056d2fe2ea006aaa771b3301ae28b/languages/java/secure-memory/src/main/java/com/godaddy/asherah/securememory/protectedmemoryimpl/ProtectedMemorySecret.java#L89-L113.

    Describe alternatives you've considered

    1. We considered using Enclave instead of LockedBuffer but we expect that for our use case, it will likely result in higher unmanaged memory usage (lot of caching and concurrent reads of keys).
    2. We've considered seeing if we can replicate the page boundary calculations to get an unsafe handle on the inner region start, but this seems very messy and error prone.
    3. We're considering replicating our Secure Memory implementation in Go, similar to what we did for Java/C#, but we're hoping to use your implementation for Go instead. The only other thing that may be an issue for us is whether the guard pages cause too much unmanaged memory in our workloads, but we'll cross that bridge when we get there.

    Additional context Think I covered all the details. Let me know if you have any questions on this. I can add the script that was used to verify the memory is readable if you'd like.

    proposal resolved 
    opened by jpaskhay 9
  • How to invalidate Enclaves?

    How to invalidate Enclaves?

    I'm implementing a transparently encrypted in-memory filesystem, and I'm storing the data of in-memory files as pointers to Enclaves *memguard.Enclave. I'm not sure what to do when I need to delete a file, or truncate a file to 0. I know that LockedBuffers can be destroyed with the Destroy method, but Enclaves don't have such a method.

    I'm also aware that when memguard.Purge is called, Enclaves are rendered useless by rolling the decryption key for them, which makes sense. How then can I safely invalidate a single enclave at will? Is that possible?

    question 
    opened by capnspacehook 9
  • Memguard must manage memory allocation to work

    Memguard must manage memory allocation to work

    See HN article for more detail. TL;DR, golang does not specify any particular semantics about memory addresses. Calling mlock on a go-managed memory address provide little to nothing in the way of guarantees, because that memory will be copied and moved around as the runtime sees fit.

    This is pretty much unavoidable. The address you call mlock on isn't even guaranteed to be the address passed in via memlock.Lock(b).

    bug 
    opened by stouset 9
  • Q: panic: <memcall> could not acquire lock

    Q: panic: could not acquire lock

    Hi, I am just wasting some time so I thought I'd compare performance requirements and I am getting panic from enclave.Open(). Any idea why?

    package whatever
    
    import (
    	"github.com/awnumar/memguard"
    	"testing"
    )
    
    func BenchmarkEnclaveOpen(b *testing.B) {
    	secret := []byte("secret secret secret")
    	e := memguard.NewEnclave(secret)
    
    	for i := 0; i < b.N; i++ {
    		e.Open()
    	}
    }
    
    func BenchmarkEnclaveOpenRead(b *testing.B) {
    	secret := []byte("secret secret secret")
    	e := memguard.NewEnclave(secret)
    
    	for i := 0; i < b.N; i++ {
    		lb, _ := e.Open()
    		lb.String()
    	}
    }
    
    func BenchmarkLBRead(b *testing.B) {
    	secret := []byte("secret secret secret")
    	lb := memguard.NewBufferFromBytes(secret)
    
    	for i := 0; i < b.N; i++ {
    		lb.String()
    	}
    }
    
    question resolved 
    opened by ghost 8
  • proposal: minimise the amount of unmanaged memory

    proposal: minimise the amount of unmanaged memory

    Is your feature request related to a problem? Please describe. Using guard pages has a tradeoff of taking up more unmanaged memory pages, which could be a potential concern in high traffic scenarios.

    Describe the solution you'd like Would be nice if there was an option to skip use guard pages when creating LockedBuffers. Can obviously keep using them by default but allow the user to pass in an option to avoid them. Whether this is exposed as part of the Enclave related usage should be considered, but could probably be handled separately, if needed.

    Describe alternatives you've considered Considered using Enclave, but in the expected traffic/usage patterns (cached keys, multiple concurrent users), it would likely lead to more unmanaged memory usage.

    Additional context N/A

    performance proposal 
    opened by jpaskhay 4
Releases(v0.22.3)
Owner
Awn
Security researcher and programmer.
Awn
Camera Control is a software "remote control" for conference cameras, e.g. Tenveo NV10U.

Camera Control Camera Control is a software "remote control" for conference cameras, e.g. Tenveo NV10U. Smart access to stored positions and zoom sett

Jürgen Högerle 1 May 1, 2022
Ots - The Bhojpur OTS is a software-as-a-service product used as an Object Tracking System based on Bhojpur.NET Platform for application delivery.

Bhojpur OTS - Object Tracking System The Bhojpur OTS is a software-as-a-service product used as an Object Tracking System based on Bhojpur.NET Platfor

Bhojpur Consulting 0 Dec 31, 2021
Pinki - Pinki helps developers ship software with authenticity

Pinki Pinki helps developers ship software with authenticity. Use it anywhere yo

Twuni 1 Jan 7, 2022
An experiment in software that has sovereignty over itself.

Sovereign An experiment in software that has sovereignty over itself. Why I Did This If you actually read through all of this, please let me know. You

Joe Henke 1 Feb 11, 2022
DERO: Secure, Anonymous Blockchain with Smart Contracts. Subscribe to Dero announcements by sending mail to [email protected] with subject: subscribe announcements

Welcome to the Dero Project DERO News Forum Wiki Explorer Source Twitter Discord Github Stats WebWallet Medium Table of Contents ABOUT DERO PROJECT DE

null 274 May 22, 2022
fastrand implements a cryptographically secure pseudorandom number generator.

10x faster than crypto/rand. Uses securely allocated memory. The generator is seeded using the system's default entropy source, and thereafter produces random values via repeated hashing. As a result, fastrand can generate randomness much faster than crypto/rand, and generation cannot fail beyond a potential panic during init().

Awn 152 Jul 18, 2022
A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.

A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.

Filippo Valsorda 11.1k Aug 17, 2022
A simple, secure self-destructing message service, using HashiCorp Vault product as a backend

sup3rS3cretMes5age! A simple, secure self-destructing message service, using Has

Karn Wong 0 Mar 5, 2022
OpenZeppelin Contracts is a library for secure smart contract development.

A library for secure smart contract development. Build on a solid foundation of community-vetted code. Implementations of standards like ERC20 and ERC

OpenZeppelin 19.4k Aug 18, 2022
Monero: the secure, private, untraceable cryptocurrency

Monero Copyright (c) 2014-2021 The Monero Project. Portions Copyright (c) 2012-2013 The Cryptonote developers. Table of Contents Development resources

The Monero Project 7.2k Aug 18, 2022
ChainMaker, a blockchain platform for building secure

ChainMaker, a blockchain platform for building secure, trustworthy value-exchange networks to power the new global digital economy. ChainMaker aim

Devin 4 Jul 28, 2022
A tiny secure-random password generator

go-psw A tiny golang tool for generating a crypto-random password in a terminal. Installation go install github.com/hedhyw/go-psw/cmd/[email protected] Usage

Maxim Krivchun 1 Jun 23, 2022
Smart.go is a pure Golang library to access disk low-level S.M.A.R.T. information

Smart.go is a pure Golang library to access disk low-level S.M.A.R.T. information. Smart.go tries to match functionality provided by smartctl but with golang API.

Anatol Pomozov 105 Aug 14, 2022
Frans Sebastian 1 Feb 14, 2022
Small utility to sign a small json containing basic kyc information. The key generated by it is fully compatible with cosmos based chains.

Testnet signer utility This utility generates a signed JSON-formatted ID to prove ownership of a key used to submit tx on the blockchain. This testnet

Archway Network 61 Jul 29, 2022
Get any cryptocurrencies ticker and trade data in real time from multiple exchanges and then save it in multiple storage systems.

Cryptogalaxy is an app which will get any cryptocurrencies ticker and trade data in real time from multiple exchanges and then saves it in multiple storage systems.

Pavan Shetty 100 Jul 23, 2022
A Go client and CLI for Filecoin Storage Auctions.

go-auctions-client A Go library and CLI to interact with Filecoin Storage Auctions. Join us on our public Slack channel for news, discussions, and sta

textile.io 4 Jan 7, 2022
An implementation of the Filecoin Distributed Storage Network

Project Lotus - 莲 Lotus is an implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the Filecoin Spec

null 0 Oct 27, 2021
Secure software enclave for storage of sensitive information in memory.

MemGuard Software enclave for storage of sensitive information in memory. This package attempts to reduce the likelihood of sensitive data being expos

Awn 2.2k Aug 17, 2022
Secure logger in Go to avoid output sensitive data in log

zlog A main distinct feature of zlog is secure logging that avoid to output secret/sensitive values to log. The feature reduce risk to store secret va

Masayoshi Mizutani 23 May 2, 2022
ARP spoofing tool based on go language, supports LAN host scanning, ARP poisoning, man-in-the-middle attack, sensitive information sniffing, HTTP packet sniffing

[ARP Spoofing] [Usage] Commands: clear clear the screen cut 通过ARP欺骗切断局域网内某台主机的网络 exit exit the program help display help hosts 主机管理功能 loot 查看嗅探到的敏感信息

Re 42 Jul 22, 2022
Sensitive information protection toolkit

godlp 一、简介 为了保障企业的数据安全和隐私安全,godlp 提供了一系列针对敏感数据的识别和处置方案, 其中包括敏感数据识别算法,数据脱敏处理方式,业务自定义的配置选项和海量数据处理能力。 godlp 能够应用多种隐私合规标准,对原始数据进行分级打标、判断敏感级别和实施相应的脱敏处理。 In

Bytedance Inc. 570 Aug 9, 2022
Otx - otx tool can scrap to find sensitive information and vulnerable endpoint urls.

otx Description This tool is base on AlienVault Open Threat Exchange (OTX)? and this tool can help you to extract all the urls endpoints which can be

ShaneKhant 4 Feb 9, 2022
A Simple to use golang masking tool to mask sensitive information from go-lang data-structures

Golang Masking Tool Golang Masking Tool is a simple utility of creating a masker tool which you can use to mask sensitive information. You can use a v

Anuraag Gupta 15 Aug 9, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Aug 13, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Aug 13, 2022
Openshift's hpessa-exporter allows users to export SMART information of local storage devices as Prometheus metrics, by using HPE Smart Storage Administrator tool

hpessa-exporter Overview Openshift's hpessa-exporter allows users to export SMART information of local storage devices as Prometheus metrics, by using

Shachar Sharon 0 Jan 17, 2022
The Container Storage Interface (CSI) Driver for Fortress Block Storage This driver allows you to use Fortress Block Storage with your container orchestrator

fortress-csi The Container Storage Interface (CSI) Driver for Fortress Block Storage This driver allows you to use Fortress Block Storage with your co

Fortress 0 Jan 23, 2022
EarlyBird is a sensitive data detection tool capable of scanning source code repositories for clear text password violations, PII, outdated cryptography methods, key files and more.

EarlyBird is a sensitive data detection tool capable of scanning source code repositories for clear text password violations, PII, outdated cryptograp

American Express 502 Aug 9, 2022