key = 33D890D33F91D52FC9B405A0DDA65336C3C4B557A3D79FE69AB674BE82C5C3D2
iv = 677C95C475C0E057B739750748608A49
Wie wird dieser Schlüssel generiert? (C-Code als Antwort wäre zu großartig, um danach zu fragen :)) Außerdem, wie wird das iv generiert?
Sieht für mich nach einer Art Hex aus.
Einzeln
OpenSSL verwendet die Funktion EVP_BytesToKey. Den Aufruf dazu findet ihr in apps/enc.c. Das enc Dienstprogramm verwendet, um den MD5-Digest standardmäßig im Key Derivation Algorithm (KDF) zu verwenden, wenn Sie mit dem keinen anderen Digest angegeben haben -md Streit. Jetzt verwendet es standardmäßig SHA-256. Hier ist ein funktionierendes Beispiel mit MD5:
OpenSSL 1.1.0c hat den in einigen internen Komponenten verwendeten Digest-Algorithmus geändert. Früher wurde MD5 verwendet und mit 1.1.0 auf SHA256 umgestellt. Seien Sie vorsichtig, dass die Änderung Sie nicht in beiden betrifft EVP_BytesToKey und Befehle wie openssl enc.
das hat mir das Leben gerettet. Ich konnte den Schlüssel von openssl und iv nicht mit Passphrase und Salt (in ios) abrufen. Nach dem Einbetten von Openssl-Bibliotheken in mein Projekt konnte ich diese verwenden.
– Furkan Mustafa
11. April 2012 um 8:52 Uhr
Gibt es eine Implementierung dieser Funktion oder ähnliches in Crypto++?
– goji
8. September 2012 um 9:37 Uhr
@ Troy: Ich weiß es nicht. Sie sollten es wahrscheinlich als Frage stellen, anstatt es zu kommentieren.
– individuell
10. September 2012 um 0:08 Uhr
Ist es möglich, ein Zeichen* oder eine Datei mit dieser Methode zu verschlüsseln, z. B. mit C:\>openssl enc –e -in data.bin -out data.enc -aes-256-cbc -p –nosalt , wo data.bin ist die Eingabedatei und data.enc die verschlüsselte Datei ?
– angereichert
6. September 2013 um 14:51 Uhr
Beachten Sie, dass enc Die Standardeinstellung auf SHA-256 ist nur in 1.1.0 enthalten, das ab Juni 2016 noch Beta ist.
– dave_thompson_085
10. Juni 2016 um 15:52 Uhr
spaceMonkey
Wenn jemand nach der Implementierung des gleichen in SWIFT sucht, habe ich das konvertiert EVP_BytesToKey schnell
/*
- parameter keyLen: keyLen
- parameter ivLen: ivLen
- parameter digest: digest e.g "md5" or "sha1"
- parameter salt: salt
- parameter data: data
- parameter count: count
- returns: key and IV respectively
*/
open static func evpBytesToKey(_ keyLen:Int, ivLen:Int, digest:String, salt:[UInt8], data:Data, count:Int)-> [[UInt8]] {
let saltData = Data(bytes: UnsafePointer<UInt8>(salt), count: Int(salt.count))
var both = [[UInt8]](repeating: [UInt8](), count: 2)
var key = [UInt8](repeating: 0,count: keyLen)
var key_ix = 0
var iv = [UInt8](repeating: 0,count: ivLen)
var iv_ix = 0
var nkey = keyLen;
var niv = ivLen;
var i = 0
var addmd = 0
var md:Data = Data()
var md_buf:[UInt8]
while true {
addmd = addmd + 1
md.append(data)
md.append(saltData)
if(digest=="md5"){
md = NSData(data:md.md5()) as Data
}else if (digest == "sha1"){
md = NSData(data:md.sha1()) as Data
}
for _ in 1...(count-1){
if(digest=="md5"){
md = NSData(data:md.md5()) as Data
}else if (digest == "sha1"){
md = NSData(data:md.sha1()) as Data
}
}
md_buf = Array (UnsafeBufferPointer(start: md.bytes, count: md.count))
// md_buf = Array(UnsafeBufferPointer(start: md.bytes.bindMemory(to: UInt8.self, capacity: md.count), count: md.length))
i = 0
if (nkey > 0) {
while(true) {
if (nkey == 0){
break
}
if (i == md.count){
break
}
key[key_ix] = md_buf[i];
key_ix = key_ix + 1
nkey = nkey - 1
i = i + 1
}
}
if (niv > 0 && i != md_buf.count) {
while(true) {
if (niv == 0){
break
}
if (i == md_buf.count){
break
}
iv[iv_ix] = md_buf[i]
iv_ix = iv_ix + 1
niv = niv - 1
i = i + 1
}
}
if (nkey == 0 && niv == 0) {
break
}
}
both[0] = key
both[1] = iv
return both
}
ich benutze CryptoSwift für den Hasch. Dies ist ein viel saubererer Weg, da Apples OpenSSL in iOS nicht empfiehlt
Update: Swift 3
“Dies ist ein viel saubererer Weg, da Apples OpenSSL in iOS nicht empfiehlt …” – OpenSSL wird aktualisiert; iOS wird aufgegeben. Verlassen Sie sich langfristig nicht auf Apple.
– jww
15. Juli 2016 um 17:23 Uhr
@jww aus meiner Erfahrung, wenn Apple “Nicht empfohlen” sagt, muss ernst genommen werden. Ich stimme dem zu, was du sagst, aber meine App wird nicht abgelehnt. Ich weiß, dass viele Leute immer noch OpenSSL in iOS verwenden (ich auch). Ich bin wirklich erschrocken, welche Entscheidungen Apple trifft
– SpaceMonkey
15. Juli 2016 um 18:05 Uhr
Funktioniert diese Swift-Version tatsächlich? Sie verwenden die Variable “addmd” nicht und haben die Rückkopplung des letzten Digests in den nächsten nach dem ersten Durchlaufen der Schleife weggelassen …
– PatchyFog
5. April 2017 um 6:21 Uhr
Ich nehme an, das liegt daran, dass der Digest in der ersten Schleife Ihrer Verwendung groß genug ist, um Ihren Schlüssel und IV zu füllen. Wenn Sie mehr Digest erstellen müssten, indem Sie Ihre äußere Schleife mehr als einmal nehmen, wäre das “rechte Ende” Ihrer Ausgabe falsch. Je nach Größe der angeforderten keyLen können diese fehlerhaften Bytes am rechten Ende des Ausgabeschlüssels oder im IV liegen.
– PatchyFog
7. April 2017 um 15:04 Uhr
Hier ist eine Version für mbedTLS / Polar SSL – getestet und funktioniert.
typedef int bool;
#define false 0
#define true (!false)
//------------------------------------------------------------------------------
static bool EVP_BytesToKey( const unsigned int nDesiredKeyLen, const unsigned char* salt,
const unsigned char* password, const unsigned int nPwdLen,
unsigned char* pOutKey, unsigned char* pOutIV )
{
// This is a re-implemntation of openssl's password to key & IV routine for mbedtls.
// (See openssl apps/enc.c and /crypto/evp/evp_key.c) It is not any kind of
// standard (e.g. PBKDF2), and it only uses an interation count of 1, so it's
// pretty crappy. MD5 is used as the digest in Openssl 1.0.2, 1.1 and late
// use SHA256. Since this is for embedded system, I figure you know what you've
// got, so I made it compile-time configurable.
//
// The signature has been re-jiggered to make it less general.
//
// See: https://wiki.openssl.org/index.php/Manual:EVP_BytesToKey(3)
// And: https://www.cryptopp.com/wiki/OPENSSL_EVP_BytesToKey
#define IV_BYTE_COUNT 16
#if BTK_USE_MD5
# define DIGEST_BYTE_COUNT 16 // MD5
#else
# define DIGEST_BYTE_COUNT 32 // SHA
#endif
bool bRet;
unsigned char md_buf[ DIGEST_BYTE_COUNT ];
mbedtls_md_context_t md_ctx;
bool bAddLastMD = false;
unsigned int nKeyToGo = nDesiredKeyLen; // 32, typical
unsigned int nIVToGo = IV_BYTE_COUNT;
mbedtls_md_init( &md_ctx );
#if BTK_USE_MD5
int rc = mbedtls_md_setup( &md_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ), 0 );
#else
int rc = mbedtls_md_setup( &md_ctx, mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), 0 );
#endif
if (rc != 0 )
{
fprintf( stderr, "mbedutils_md_setup() failed -0x%04x\n", -rc );
bRet = false;
goto exit;
}
while( 1 )
{
mbedtls_md_starts( &md_ctx ); // start digest
if ( bAddLastMD == false ) // first time
{
bAddLastMD = true; // do it next time
}
else
{
mbedtls_md_update( &md_ctx, &md_buf[0], DIGEST_BYTE_COUNT );
}
mbedtls_md_update( &md_ctx, &password[0], nPwdLen );
mbedtls_md_update( &md_ctx, &salt[0], 8 );
mbedtls_md_finish( &md_ctx, &md_buf[0] );
//
// Iteration loop here in original removed as unused by "openssl enc"
//
// Following code treats the output key and iv as one long, concatentated buffer
// and smears as much digest across it as is available. If not enough, it takes the
// big, enclosing loop, makes more digest, and continues where it left off on
// the last iteration.
unsigned int ii = 0; // index into mb_buf
if ( nKeyToGo != 0 ) // still have key to fill in?
{
while( 1 )
{
if ( nKeyToGo == 0 ) // key part is full/done
break;
if ( ii == DIGEST_BYTE_COUNT ) // ran out of digest, so loop
break;
*pOutKey++ = md_buf[ ii ]; // stick byte in output key
nKeyToGo--;
ii++;
}
}
if ( nIVToGo != 0 // still have fill up IV
&& // and
ii != DIGEST_BYTE_COUNT // have some digest available
)
{
while( 1 )
{
if ( nIVToGo == 0 ) // iv is full/done
break;
if ( ii == DIGEST_BYTE_COUNT ) // ran out of digest, so loop
break;
*pOutIV++ = md_buf[ ii ]; // stick byte in output IV
nIVToGo--;
ii++;
}
}
if ( nKeyToGo == 0 && nIVToGo == 0 ) // output full, break main loop and exit
break;
} // outermost while loop
bRet = true;
exit:
mbedtls_md_free( &md_ctx );
return bRet;
}
Wenn jemand, der hier vorbeikommt, nach einer funktionierenden, performanten Referenzimplementierung in Haskell sucht, hier ist sie:
import Crypto.Hash
import qualified Data.ByteString as B
import Data.ByteArray (convert)
import Data.Monoid ((<>))
evpBytesToKey :: HashAlgorithm alg =>
Int -> Int -> alg -> Maybe B.ByteString -> B.ByteString -> (B.ByteString, B.ByteString)
evpBytesToKey keyLen ivLen alg mSalt password =
let bytes = B.concat . take required . iterate go $ hash' passAndSalt
(key, rest) = B.splitAt keyLen bytes
in (key, B.take ivLen rest)
where
hash' = convert . hashWith alg
required = 1 + ((keyLen + ivLen - 1) `div` hashDigestSize alg)
passAndSalt = maybe password (password <>) mSalt
go = hash' . (<> passAndSalt)
Es verwendet Hash-Algorithmen, die von bereitgestellt werden Kryptonit Paket. Die Argumente sind der gewünschte Schlüssel und die IV-Größe in Bytes, der zu verwendende Hash-Algorithmus (wie z (undefined :: MD5)), optional Salt und das Passwort. Das Ergebnis ist ein Tupel aus Schlüssel und IV.
12162900cookie-checkPasswort für Schlüsselfunktion kompatibel mit OpenSSL-Befehlen?yes