Migrazione degli utenti da un'app esistente

Questo documento mostra come migrare gli utenti da un'app esistente a Identity Platform.

Prima di iniziare

Utilizzo dell'SDK Admin

L'SDK Admin ti consente di importare gli utenti senza esportare i dati utente in formato CSV o JSON. Puoi importare gli utenti in tutti i provider supportati da Identity Platform, inclusi OAuth, SAML e OIDC.

È possibile importare fino a 1000 utenti in una singola chiamata API. L'operazione di importazione è ottimizzata per la velocità e non verifica la presenza di campi duplicati. L'importazione di un utente che entra in conflitto con un uid esistente sostituirà l'utente esistente. L'importazione di un utente con qualsiasi altro campo duplicato (ad esempio email) comporterà la creazione di un utente aggiuntivo con lo stesso valore.

L'SDK Admin tenta di caricare l'intero elenco di utenti forniti, anche quando si verifica un errore specifico dell'utente. L'operazione restituisce un risultato con il riepilogo delle importazioni riuscite e non riuscite. I dettagli dell'errore vengono restituiti per ogni importazione di utenti non riuscita.

Importazione di utenti con password con hash HMAC

Gli algoritmi di hashing HMAC includono HMAC_MD5, HMAC_SHA1, HMAC_SHA256 e HMAC_SHA512. Dovrai fornire la chiave del firmatario dell'hash.

Node.js

getAuth()
  .importUsers(
    [
      {
        uid: 'some-uid',
        email: 'user@example.com',
        // Must be provided in a byte buffer.
        passwordHash: Buffer.from('password-hash'),
        // Must be provided in a byte buffer.
        passwordSalt: Buffer.from('salt'),
      },
    ],
    {
      hash: {
        algorithm: 'HMAC_SHA256',
        // Must be provided in a byte buffer.
        key: Buffer.from('secret'),
      },
    }
  )
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setEmail("user@example.com")
      .setPasswordHash("password-hash".getBytes())
      .setPasswordSalt("salt".getBytes())
      .build());
  UserImportOptions options = UserImportOptions.withHash(
      HmacSha256.builder()
          .setKey("secret".getBytes())
          .build());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        email='user@example.com',
        password_hash=b'password_hash',
        password_salt=b'salt'
    ),
]

hash_alg = auth.UserImportHash.hmac_sha256(key=b'secret')
try:
    result = auth.import_users(users, hash_alg=hash_alg)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		Email("user@example.com").
		PasswordHash([]byte("password-hash")).
		PasswordSalt([]byte("salt")),
}
h := hash.HMACSHA256{
	Key: []byte("secret"),
}
result, err := client.ImportUsers(ctx, users, auth.WithHash(h))
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Importazione di utenti con password con hash MD5, SHA e PBKDF

Gli algoritmi di hashing MD5, SHA e PBKDF includono MD5, SHA1, SHA256, SHA512, PBKDF_SHA1 e PBKDF2_SHA256. Dovrai fornire i round utilizzati per l'hashing della password (tra 0 e 8192 per MD5, tra 1 e 8192 per SHA1, SHA256 e SHA512, e tra 0 e 120000 per PBKDF_SHA1 e PBKDF2_SHA256).

Node.js

getAuth()
  .importUsers(
    [
      {
        uid: 'some-uid',
        email: 'user@example.com',
        // Must be provided in a byte buffer.
        passwordHash: Buffer.from('password-hash'),
        // Must be provided in a byte buffer.
        passwordSalt: Buffer.from('salt'),
      },
    ],
    {
      hash: {
        algorithm: 'PBKDF2_SHA256',
        rounds: 100000,
      },
    }
  )
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setEmail("user@example.com")
      .setPasswordHash("password-hash".getBytes())
      .setPasswordSalt("salt".getBytes())
      .build());
  UserImportOptions options = UserImportOptions.withHash(
      Pbkdf2Sha256.builder()
          .setRounds(100000)
          .build());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        email='user@example.com',
        password_hash=b'password_hash',
        password_salt=b'salt'
    ),
]

hash_alg = auth.UserImportHash.pbkdf2_sha256(rounds=100000)
try:
    result = auth.import_users(users, hash_alg=hash_alg)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		Email("user@example.com").
		PasswordHash([]byte("password-hash")).
		PasswordSalt([]byte("salt")),
}
h := hash.PBKDF2SHA256{
	Rounds: 100000,
}
result, err := client.ImportUsers(ctx, users, auth.WithHash(h))
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Importazione di utenti con password con hash SCRYPT standard

L'SDK Admin supporta l'algoritmo standard SCRYPT e una versione modificata interna. Sono richiesti i seguenti parametri:

  • memoryCost: il costo di CPU/memoria dell'algoritmo di hashing.
  • parallelization: la parallelizzazione dell'algoritmo di hashing.
  • blockSize: la dimensione del blocco (in genere 8) dell'algoritmo di hashing.
  • derivedKeyLength: la lunghezza della chiave derivata dell'algoritmo di hashing.

Node.js

getAuth()
  .importUsers(
    [
      {
        uid: 'some-uid',
        email: 'user@example.com',
        // Must be provided in a byte buffer.
        passwordHash: Buffer.from('password-hash'),
        // Must be provided in a byte buffer.
        passwordSalt: Buffer.from('salt'),
      },
    ],
    {
      hash: {
        algorithm: 'STANDARD_SCRYPT',
        memoryCost: 1024,
        parallelization: 16,
        blockSize: 8,
        derivedKeyLength: 64,
      },
    }
  )
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setEmail("user@example.com")
      .setPasswordHash("password-hash".getBytes())
      .setPasswordSalt("salt".getBytes())
      .build());
  UserImportOptions options = UserImportOptions.withHash(
      StandardScrypt.builder()
          .setMemoryCost(1024)
          .setParallelization(16)
          .setBlockSize(8)
          .setDerivedKeyLength(64)
          .build());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        email='user@example.com',
        password_hash=b'password_hash',
        password_salt=b'salt'
    ),
]

hash_alg = auth.UserImportHash.standard_scrypt(
    memory_cost=1024, parallelization=16, block_size=8, derived_key_length=64)
try:
    result = auth.import_users(users, hash_alg=hash_alg)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		Email("user@example.com").
		PasswordHash([]byte("password-hash")).
		PasswordSalt([]byte("salt")),
}
h := hash.StandardScrypt{
	MemoryCost:       1024,
	Parallelization:  16,
	BlockSize:        8,
	DerivedKeyLength: 64,
}
result, err := client.ImportUsers(ctx, users, auth.WithHash(h))
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Importazione di utenti con password con hash SCRYPT di Identity Platform

Identity Platform e Firebase utilizzano una versione modificata dell'algoritmo SCRYPT. Se devi migrare gli utenti da Firebase a Identity Platform o da un progetto Identity Platform a un altro, avrai bisogno dei parametri di hash interni.

Per accedere ai parametri in Identity Platform:

  1. Apri la pagina Utenti nella Google Cloud console.
  2. Fai clic su Importa utenti. Vengono visualizzati i parametri di hash della password.

Per accedere ai parametri in Firebase:

  1. Apri la scheda Utenti nella console Firebase.

  2. Seleziona Parametri di hash della password dal menu a discesa nell'angolo in alto a destra dell'elenco degli utenti. Vengono visualizzati i parametri di hash della password.

Nel codice, dovrai fornire quanto segue:

  • key: la chiave del firmatario fornita in genere nella codifica base64.
  • saltSeparator: (facoltativo) il separatore di salt fornito in genere nella codifica base64.
  • rounds: il numero di round utilizzati per l'hashing delle password.
  • memoryCost: il costo della memoria richiesto per questo algoritmo.

Node.js

getAuth()
  .importUsers(
    [
      {
        uid: 'some-uid',
        email: 'user@example.com',
        // Must be provided in a byte buffer.
        passwordHash: Buffer.from('base64-password-hash', 'base64'),
        // Must be provided in a byte buffer.
        passwordSalt: Buffer.from('base64-salt', 'base64'),
      },
    ],
    {
      hash: {
        algorithm: 'SCRYPT',
        // All the parameters below can be obtained from the Firebase Console's users section.
        // Must be provided in a byte buffer.
        key: Buffer.from('base64-secret', 'base64'),
        saltSeparator: Buffer.from('base64SaltSeparator', 'base64'),
        rounds: 8,
        memoryCost: 14,
      },
    }
  )
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setEmail("user@example.com")
      .setPasswordHash(BaseEncoding.base64().decode("password-hash"))
      .setPasswordSalt(BaseEncoding.base64().decode("salt"))
      .build());
  UserImportOptions options = UserImportOptions.withHash(
      Scrypt.builder()
          // All the parameters below can be obtained from the Firebase Console's "Users"
          // section. Base64 encoded parameters must be decoded into raw bytes.
          .setKey(BaseEncoding.base64().decode("base64-secret"))
          .setSaltSeparator(BaseEncoding.base64().decode("base64-salt-separator"))
          .setRounds(8)
          .setMemoryCost(14)
          .build());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        email='user@example.com',
        password_hash=base64.urlsafe_b64decode('password_hash'),
        password_salt=base64.urlsafe_b64decode('salt')
    ),
]

# All the parameters below can be obtained from the Firebase Console's "Users"
# section. Base64 encoded parameters must be decoded into raw bytes.
hash_alg = auth.UserImportHash.scrypt(
    key=base64.b64decode('base64_secret'),
    salt_separator=base64.b64decode('base64_salt_separator'),
    rounds=8,
    memory_cost=14
)
try:
    result = auth.import_users(users, hash_alg=hash_alg)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

b64URLdecode := func(s string) []byte {
	b, err := base64.URLEncoding.DecodeString(s)
	if err != nil {
		log.Fatalln("Failed to decode string", err)
	}

	return b
}
b64Stddecode := func(s string) []byte {
	b, err := base64.StdEncoding.DecodeString(s)
	if err != nil {
		log.Fatalln("Failed to decode string", err)
	}
	return b
}
// Users retrieved from Firebase Auth's backend need to be base64URL decoded
users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		Email("user@example.com").
		PasswordHash(b64URLdecode("password-hash")).
		PasswordSalt(b64URLdecode("salt")),
}

// All the parameters below can be obtained from the Firebase Console's "Users"
// section. Base64 encoded parameters must be decoded into raw bytes.
h := hash.Scrypt{
	Key:           b64Stddecode("base64-secret"),
	SaltSeparator: b64Stddecode("base64-salt-separator"),
	Rounds:        8,
	MemoryCost:    14,
}
result, err := client.ImportUsers(ctx, users, auth.WithHash(h))
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Importazione di utenti con password con hash BCRYPT

Non sono necessari parametri aggiuntivi o salt della password per le password con hash BCRYPT.

Node.js

getAuth()
  .importUsers(
    [
      {
        uid: 'some-uid',
        email: 'user@example.com',
        // Must be provided in a byte buffer.
        passwordHash: Buffer.from('password-hash'),
      },
    ],
    {
      hash: {
        algorithm: 'BCRYPT',
      },
    }
  )
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setEmail("user@example.com")
      .setPasswordHash("password-hash".getBytes())
      .setPasswordSalt("salt".getBytes())
      .build());
  UserImportOptions options = UserImportOptions.withHash(Bcrypt.getInstance());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        email='user@example.com',
        password_hash=b'password_hash',
        password_salt=b'salt'
    ),
]

hash_alg = auth.UserImportHash.bcrypt()
try:
    result = auth.import_users(users, hash_alg=hash_alg)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		Email("user@example.com").
		PasswordHash([]byte("password-hash")).
		PasswordSalt([]byte("salt")),
}
h := hash.Bcrypt{}
result, err := client.ImportUsers(ctx, users, auth.WithHash(h))
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Importazione di utenti senza password

Se gli utenti si autenticano con un provider di identità esterno utilizzando OAuth, SAML o OIDC, non avrai accesso diretto alla loro password.

Node.js

getAuth()
  .importUsers([
    {
      uid: 'some-uid',
      displayName: 'John Doe',
      email: 'johndoe@gmail.com',
      photoURL: 'http://www.example.com/12345678/photo.png',
      emailVerified: true,
      phoneNumber: '+11234567890',
      // Set this user as admin.
      customClaims: { admin: true },
      // User with Google provider.
      providerData: [
        {
          uid: 'google-uid',
          email: 'johndoe@gmail.com',
          displayName: 'John Doe',
          photoURL: 'http://www.example.com/12345678/photo.png',
          providerId: 'google.com',
        },
      ],
    },
  ])
  .then((results) => {
    results.errors.forEach((indexedError) => {
      console.log(`Error importing user ${indexedError.index}`);
    });
  })
  .catch((error) => {
    console.log('Error importing users :', error);
  });

Java

try {
  List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder()
      .setUid("some-uid")
      .setDisplayName("John Doe")
      .setEmail("johndoe@gmail.com")
      .setPhotoUrl("http://www.example.com/12345678/photo.png")
      .setEmailVerified(true)
      .setPhoneNumber("+11234567890")
      .putCustomClaim("admin", true) // set this user as admin
      .addUserProvider(UserProvider.builder() // user with Google provider
          .setUid("google-uid")
          .setEmail("johndoe@gmail.com")
          .setDisplayName("John Doe")
          .setPhotoUrl("http://www.example.com/12345678/photo.png")
          .setProviderId("google.com")
          .build())
      .build());
  UserImportResult result = FirebaseAuth.getInstance().importUsers(users);
  for (ErrorInfo indexedError : result.getErrors()) {
    System.out.println("Failed to import user: " + indexedError.getReason());
  }
} catch (FirebaseAuthException e) {
  System.out.println("Error importing users: " + e.getMessage());
}

Python

users = [
    auth.ImportUserRecord(
        uid='some-uid',
        display_name='John Doe',
        email='johndoe@gmail.com',
        photo_url='http://www.example.com/12345678/photo.png',
        email_verified=True,
        phone_number='+11234567890',
        custom_claims={'admin': True}, # set this user as admin
        provider_data=[ # user with Google provider
            auth.UserProvider(
                uid='google-uid',
                email='johndoe@gmail.com',
                display_name='John Doe',
                photo_url='http://www.example.com/12345678/photo.png',
                provider_id='google.com'
            )
        ],
    ),
]
try:
    result = auth.import_users(users)
    for err in result.errors:
        print('Failed to import user:', err.reason)
except exceptions.FirebaseError as error:
    print('Error importing users:', error)

Vai

users := []*auth.UserToImport{
	(&auth.UserToImport{}).
		UID("some-uid").
		DisplayName("John Doe").
		Email("johndoe@gmail.com").
		PhotoURL("http://www.example.com/12345678/photo.png").
		EmailVerified(true).
		PhoneNumber("+11234567890").
		CustomClaims(map[string]interface{}{"admin": true}). // set this user as admin
		ProviderData([]*auth.UserProvider{                   // user with Google provider
			{
				UID:         "google-uid",
				Email:       "johndoe@gmail.com",
				DisplayName: "John Doe",
				PhotoURL:    "http://www.example.com/12345678/photo.png",
				ProviderID:  "google.com",
			},
		}),
}
result, err := client.ImportUsers(ctx, users)
if err != nil {
	log.Fatalln("Error importing users", err)
}
for _, e := range result.Errors {
	log.Println("Failed to import user", e.Reason)
}

Tieni presente che providerId viene utilizzato in Identity Platform per descrivere un provider specifico. Per i provider OIDC e SAML, questo valore viene definito durante la creazione. Per gli altri provider, questo valore ha un valore predefinito (ad esempio google.com o facebook.com). Puoi recuperare providerId dalle attestazioni dell'utente che ha eseguito l'accesso.

Importazione di utenti con più fattori di autenticazione

Se gli utenti esistenti hanno numeri di telefono registrati per l'utilizzo con l'autenticazione a più fattori, puoi importarli in Identity Platform.

Gli utenti con autenticazione a più fattori devono avere un indirizzo email verificato e un primo fattore supportato. Sono consentiti fino a 5 fattori secondari per utente.

Puoi importare le seguenti proprietà di autenticazione a più fattori:

Proprietà Tipo Descrizione
uid string Un ID univoco facoltativo del secondo fattore registrato. Se non viene fornito, viene generato automaticamente un casuale uid.
phoneNumber string Il numero di telefono del secondo fattore registrato. Questo numero di telefono deve essere E.164 conforme.
displayName string Un nome visualizzato facoltativo. Questo è utile se un utente ha più secondi fattori registrati.
enrollmentTime string La data di registrazione del secondo fattore, formattata come stringa UTC. Se non viene fornita, verrà utilizzata la data corrente.
factorId string L'identificatore del tipo di secondo fattore. Questo valore è sempre impostato su phone.

L'esempio seguente mostra come importare utenti con autenticazione a più fattori:

Node.js

// Up to 1000 users can be imported at once.
const userImportRecords = [
  {
    uid: 'uid1',
    email: 'user1@example.com',
    emailVerified: true,
    passwordHash: Buffer.from('passwordHash1'),
    passwordSalt: Buffer.from('salt1'),
    multiFactor: {
      enrolledFactors: [
        {
          // Enrolled second factor uid is optional.
          uid: 'uid1-unique-mfa-identifier1',
          displayName: 'Personal phone',
          phoneNumber: '+16505551234',
          factorId: 'phone',
          // Enrollment time is also optional.
          enrollmentTime: 'Fri, 22 Sep 2017 01:49:58 GMT',
        },
      ],
    },
  },
  {
    // User with multiple second factors.
    uid: 'uid2',
    email: 'user2@example.com',
    emailVerified: true,
    passwordHash: Buffer.from('passwordHash2'),
    passwordSalt: Buffer.from('salt2'),
    multiFactor: {
      enrolledFactors: [
        {
          displayName: 'Work phone',
          phoneNumber: '+16505550007',
          factorId: 'phone',
        },
        {
          displayName: 'Backup phone',
          phoneNumber:  '+16505550008',
          factorId: 'phone',
        },
      ],
    },
  },
  {
    // User with no second factor.
    uid: 'uid3',
    email: 'user3@example.com',
    passwordHash: Buffer.from('passwordHash3'),
    passwordSalt: Buffer.from('salt3'),
  },
  ...
];

const userImportOptions = {
  hash: {
    algorithm: 'HMAC_SHA256',
    key: Buffer.from('secretKey'),
  },
};

admin.auth().importUsers(userImportRecords, userImportOptions)
  .then((userImportResult) => {
    // The number of successful imports is determined via: userImportResult.successCount.
    // The number of failed imports is determined via: userImportResult.failureCount.
    // To get the error details.
    userImportResult.forEach(function(indexedError) {
      // The corresponding user that failed to upload.
      console.log(userImportRecords[indexedError.index].uid +' failed to import',
          indexedError.error);
    });
  })
  .catch((error) => {
    // Some unrecoverable error occurred that prevented the operation from running.
  });

Utilizzo dell'interfaccia a riga di comando

Se i dati utente sono archiviati in formato JSON o CSV, puoi importarli utilizzando lo strumento a riga di comando di Firebase:

  firebase auth:import account_file       \
    --hash-algo=[HASH-ALGORITHM]          \
    --hash-key=[KEY]                      \
    --salt-separator=[SALT-SEPARATOR]     \
    --rounds=[ROUNDS]                     \
    --mem-cost=[MEM-COST]                 \
    --parallelization=[PARALLELIZATION]   \
    --block-size=[BLOCK-SIZE]             \
    --dk-len=[DK-LEN]                     \
    --hash-input-order=[HASH-INPUT-ORDER] \

Per una descrizione completa di ogni parametro, consulta la documentazione di riferimento dell'interfaccia a riga di comando .

Passaggi successivi