€•chŒsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”Œparent”hsbaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ&/translations/zh_CN/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”hh2sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/zh_TW/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”hhFsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/it_IT/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”hhZsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ja_JP/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”hhnsbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ko_KR/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”hh‚sbah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/sp_SP/crypto/devel-algos”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒDeveloping Cipher Algorithms”h]”hŒDeveloping Cipher Algorithms”…””}”(hh¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh£hžhhŸŒ@/var/lib/git/docbuild/linux/Documentation/crypto/devel-algos.rst”h Kubh¢)”}”(hhh]”(h§)”}”(hŒ,Registering And Unregistering Transformation”h]”hŒ,Registering And Unregistering Transformation”…””}”(hhºhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh·hžhhŸh¶h KubhŒ paragraph”“”)”}”(hX7There are three distinct types of registration functions in the Crypto API. One is used to register a generic cryptographic transformation, while the other two are specific to HASH transformations and COMPRESSion. We will discuss the latter two in a separate chapter, here we will only look at the generic ones.”h]”hX7There are three distinct types of registration functions in the Crypto API. One is used to register a generic cryptographic transformation, while the other two are specific to HASH transformations and COMPRESSion. We will discuss the latter two in a separate chapter, here we will only look at the generic ones.”…””}”(hhÊhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Khh·hžhubhÉ)”}”(hŒ±Before discussing the register functions, the data structure to be filled with each, struct crypto_alg, must be considered -- see below for a description of this data structure.”h]”hŒ±Before discussing the register functions, the data structure to be filled with each, struct crypto_alg, must be considered -- see below for a description of this data structure.”…””}”(hhØhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K hh·hžhubhÉ)”}”(hXiThe generic registration functions can be found in include/linux/crypto.h and their definition can be seen below. The former function registers a single transformation, while the latter works on an array of transformation descriptions. The latter is useful when registering transformations in bulk, for example when a driver implements multiple transformations.”h]”hXiThe generic registration functions can be found in include/linux/crypto.h and their definition can be seen below. The former function registers a single transformation, while the latter works on an array of transformation descriptions. The latter is useful when registering transformations in bulk, for example when a driver implements multiple transformations.”…””}”(hhæhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Khh·hžhubhŒ literal_block”“”)”}”(hŒnint crypto_register_alg(struct crypto_alg *alg); int crypto_register_algs(struct crypto_alg *algs, int count);”h]”hŒnint crypto_register_alg(struct crypto_alg *alg); int crypto_register_algs(struct crypto_alg *algs, int count);”…””}”hhösbah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1hôhŸh¶h Khh·hžhubhÉ)”}”(hŒ5The counterparts to those functions are listed below.”h]”hŒ5The counterparts to those functions are listed below.”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Khh·hžhubhõ)”}”(hŒtvoid crypto_unregister_alg(struct crypto_alg *alg); void crypto_unregister_algs(struct crypto_alg *algs, int count);”h]”hŒtvoid crypto_unregister_alg(struct crypto_alg *alg); void crypto_unregister_algs(struct crypto_alg *algs, int count);”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h K"hh·hžhubhÉ)”}”(hŒòThe registration functions return 0 on success, or a negative errno value on failure. crypto_register_algs() succeeds only if it successfully registered all the given algorithms; if it fails partway through, then any changes are rolled back.”h]”hŒòThe registration functions return 0 on success, or a negative errno value on failure. crypto_register_algs() succeeds only if it successfully registered all the given algorithms; if it fails partway through, then any changes are rolled back.”…””}”(hj"hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K&hh·hžhubhÉ)”}”(hŒ•The unregistration functions always succeed, so they don't have a return value. Don't try to unregister algorithms that aren't currently registered.”h]”hŒ›The unregistration functions always succeed, so they don’t have a return value. Don’t try to unregister algorithms that aren’t currently registered.”…””}”(hj0hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K+hh·hžhubeh}”(h]”Œ,registering-and-unregistering-transformation”ah ]”h"]”Œ,registering and unregistering transformation”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kubh¢)”}”(hhh]”(h§)”}”(hŒ'Single-Block Symmetric Ciphers [CIPHER]”h]”hŒ'Single-Block Symmetric Ciphers [CIPHER]”…””}”(hjIhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjFhžhhŸh¶h K0ubhÉ)”}”(hŒ-Example of transformations: aes, serpent, ...”h]”hŒ-Example of transformations: aes, serpent, ...”…””}”(hjWhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K2hjFhžhubhÉ)”}”(hXThis section describes the simplest of all transformation implementations, that being the CIPHER type used for symmetric ciphers. The CIPHER type is used for transformations which operate on exactly one block at a time and there are no dependencies between blocks at all.”h]”hXThis section describes the simplest of all transformation implementations, that being the CIPHER type used for symmetric ciphers. The CIPHER type is used for transformations which operate on exactly one block at a time and there are no dependencies between blocks at all.”…””}”(hjehžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K4hjFhžhubh¢)”}”(hhh]”(h§)”}”(hŒRegistration specifics”h]”hŒRegistration specifics”…””}”(hjvhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjshžhhŸh¶h K:ubhÉ)”}”(hŒÄThe registration of [CIPHER] algorithm is specific in that struct crypto_alg field .cra_type is empty. The .cra_u.cipher has to be filled in with proper callbacks to implement this transformation.”h]”hŒÄThe registration of [CIPHER] algorithm is specific in that struct crypto_alg field .cra_type is empty. The .cra_u.cipher has to be filled in with proper callbacks to implement this transformation.”…””}”(hj„hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K .cia_encrypt() | '-----> CIPHERTEXT”h]”hŒKEY ---. PLAINTEXT ---. v v .cia_setkey() -> .cia_encrypt() | '-----> CIPHERTEXT”…””}”hjÖsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h KNhj©hžhubhÉ)”}”(hŒVPlease note that a pattern where .cia_setkey() is called multiple times is also valid:”h]”hŒVPlease note that a pattern where .cia_setkey() is called multiple times is also valid:”…””}”(hjähžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h KUhj©hžhubhõ)”}”(hXKKEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. v v v v .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() | | '---> CIPHERTEXT1 '---> CIPHERTEXT2”h]”hXKKEY1 --. PLAINTEXT1 --. KEY2 --. PLAINTEXT2 --. v v v v .cia_setkey() -> .cia_encrypt() -> .cia_setkey() -> .cia_encrypt() | | '---> CIPHERTEXT1 '---> CIPHERTEXT2”…””}”hjòsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h K[hj©hžhubeh}”(h]”Œ(cipher-definition-with-struct-cipher-alg”ah ]”h"]”Œ(cipher definition with struct cipher_alg”ah$]”h&]”uh1h¡hjFhžhhŸh¶h KCubeh}”(h]”Œ%single-block-symmetric-ciphers-cipher”ah ]”h"]”Œ'single-block symmetric ciphers [cipher]”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K0ubh¢)”}”(hhh]”(h§)”}”(hŒMulti-Block Ciphers”h]”hŒMulti-Block Ciphers”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjhžhhŸh¶h KcubhÉ)”}”(hŒ3Example of transformations: cbc(aes), chacha20, ...”h]”hŒ3Example of transformations: cbc(aes), chacha20, ...”…””}”(hj!hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h KehjhžhubhÉ)”}”(hX This section describes the multi-block cipher transformation implementations. The multi-block ciphers are used for transformations which operate on scatterlists of data supplied to the transformation functions. They output the result into a scatterlist of data as well.”h]”hX This section describes the multi-block cipher transformation implementations. The multi-block ciphers are used for transformations which operate on scatterlists of data supplied to the transformation functions. They output the result into a scatterlist of data as well.”…””}”(hj/hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Kghjhžhubh¢)”}”(hhh]”(h§)”}”(hŒRegistration Specifics”h]”hŒRegistration Specifics”…””}”(hj@hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj=hžhhŸh¶h KmubhÉ)”}”(hŒsThe registration of multi-block cipher algorithms is one of the most standard procedures throughout the crypto API.”h]”hŒsThe registration of multi-block cipher algorithms is one of the most standard procedures throughout the crypto API.”…””}”(hjNhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Kohj=hžhubhÉ)”}”(hX„Note, if a cipher implementation requires a proper alignment of data, the caller should use the functions of crypto_skcipher_alignmask() to identify a memory alignment mask. The kernel crypto API is able to process requests that are unaligned. This implies, however, additional overhead as the kernel crypto API needs to perform the realignment of the data which may imply moving of data.”h]”hX„Note, if a cipher implementation requires a proper alignment of data, the caller should use the functions of crypto_skcipher_alignmask() to identify a memory alignment mask. The kernel crypto API is able to process requests that are unaligned. This implies, however, additional overhead as the kernel crypto API needs to perform the realignment of the data which may imply moving of data.”…””}”(hj\hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Krhj=hžhubeh}”(h]”Œid1”ah ]”h"]”h$]”j¦ah&]”uh1h¡hjhžhhŸh¶h Kmj¨Kubh¢)”}”(hhh]”(h§)”}”(hŒ*Cipher Definition With struct skcipher_alg”h]”hŒ*Cipher Definition With struct skcipher_alg”…””}”(hjthžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjqhžhhŸh¶h KzubhÉ)”}”(hŒtStruct skcipher_alg defines a multi-block cipher, or more generally, a length-preserving symmetric cipher algorithm.”h]”hŒtStruct skcipher_alg defines a multi-block cipher, or more generally, a length-preserving symmetric cipher algorithm.”…””}”(hj‚hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K|hjqhžhubeh}”(h]”Œ*cipher-definition-with-struct-skcipher-alg”ah ]”h"]”Œ*cipher definition with struct skcipher_alg”ah$]”h&]”uh1h¡hjhžhhŸh¶h Kzubh¢)”}”(hhh]”(h§)”}”(hŒScatterlist handling”h]”hŒScatterlist handling”…””}”(hj›hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj˜hžhhŸh¶h K€ubhÉ)”}”(hX'Some drivers will want to use the Generic ScatterWalk in case the hardware needs to be fed separate chunks of the scatterlist which contains the plaintext and will contain the ciphertext. Please refer to the ScatterWalk interface offered by the Linux kernel scatter / gather list implementation.”h]”hX'Some drivers will want to use the Generic ScatterWalk in case the hardware needs to be fed separate chunks of the scatterlist which contains the plaintext and will contain the ciphertext. Please refer to the ScatterWalk interface offered by the Linux kernel scatter / gather list implementation.”…””}”(hj©hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K‚hj˜hžhubeh}”(h]”Œscatterlist-handling”ah ]”h"]”Œscatterlist handling”ah$]”h&]”uh1h¡hjhžhhŸh¶h K€ubeh}”(h]”Œmulti-block-ciphers”ah ]”h"]”Œmulti-block ciphers”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kcubh¢)”}”(hhh]”(h§)”}”(hŒHashing [HASH]”h]”hŒHashing [HASH]”…””}”(hjÊhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjÇhžhhŸh¶h K‰ubhÉ)”}”(hŒ8Example of transformations: crc32, md5, sha1, sha256,...”h]”hŒ8Example of transformations: crc32, md5, sha1, sha256,...”…””}”(hjØhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K‹hjÇhžhubh¢)”}”(hhh]”(h§)”}”(hŒ0Registering And Unregistering The Transformation”h]”hŒ0Registering And Unregistering The Transformation”…””}”(hjéhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjæhžhhŸh¶h KŽubhÉ)”}”(hXThere are multiple ways to register a HASH transformation, depending on whether the transformation is synchronous [SHASH] or asynchronous [AHASH] and the amount of HASH transformations we are registering. You can find the prototypes defined in include/crypto/internal/hash.h:”h]”hXThere are multiple ways to register a HASH transformation, depending on whether the transformation is synchronous [SHASH] or asynchronous [AHASH] and the amount of HASH transformations we are registering. You can find the prototypes defined in include/crypto/internal/hash.h:”…””}”(hj÷hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Khjæhžhubhõ)”}”(hŒ¤int crypto_register_ahash(struct ahash_alg *alg); int crypto_register_shash(struct shash_alg *alg); int crypto_register_shashes(struct shash_alg *algs, int count);”h]”hŒ¤int crypto_register_ahash(struct ahash_alg *alg); int crypto_register_shash(struct shash_alg *alg); int crypto_register_shashes(struct shash_alg *algs, int count);”…””}”hjsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h K—hjæhžhubhÉ)”}”(hŒUThe respective counterparts for unregistering the HASH transformation are as follows:”h]”hŒUThe respective counterparts for unregistering the HASH transformation are as follows:”…””}”(hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Khjæhžhubhõ)”}”(hŒ­void crypto_unregister_ahash(struct ahash_alg *alg); void crypto_unregister_shash(struct shash_alg *alg); void crypto_unregister_shashes(struct shash_alg *algs, int count);”h]”hŒ­void crypto_unregister_ahash(struct ahash_alg *alg); void crypto_unregister_shash(struct shash_alg *alg); void crypto_unregister_shashes(struct shash_alg *algs, int count);”…””}”hj!sbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h K¢hjæhžhubeh}”(h]”Œ0registering-and-unregistering-the-transformation”ah ]”h"]”Œ0registering and unregistering the transformation”ah$]”h&]”uh1h¡hjÇhžhhŸh¶h KŽubh¢)”}”(hhh]”(h§)”}”(hŒ5Cipher Definition With struct shash_alg and ahash_alg”h]”hŒ5Cipher Definition With struct shash_alg and ahash_alg”…””}”(hj:hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj7hžhhŸh¶h K©ubhÉ)”}”(hX_Here are schematics of how these functions are called when operated from other part of the kernel. Note that the .setkey() call might happen before or after any of these schematics happen, but must not happen during any of these are in-flight. Please note that calling .init() followed immediately by .final() is also a perfectly valid transformation.”h]”hX_Here are schematics of how these functions are called when operated from other part of the kernel. Note that the .setkey() call might happen before or after any of these schematics happen, but must not happen during any of these are in-flight. Please note that calling .init() followed immediately by .final() is also a perfectly valid transformation.”…””}”(hjHhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h K«hj7hžhubhõ)”}”(hXÜI) DATA -----------. v .init() -> .update() -> .final() ! .update() might not be called ^ | | at all in this scenario. '----' '---> HASH II) DATA -----------.-----------. v v .init() -> .update() -> .finup() ! .update() may not be called ^ | | at all in this scenario. '----' '---> HASH III) DATA -----------. v .digest() ! The entire process is handled | by the .digest() call. '---------------> HASH”h]”hXÜI) DATA -----------. v .init() -> .update() -> .final() ! .update() might not be called ^ | | at all in this scenario. '----' '---> HASH II) DATA -----------.-----------. v v .init() -> .update() -> .finup() ! .update() may not be called ^ | | at all in this scenario. '----' '---> HASH III) DATA -----------. v .digest() ! The entire process is handled | by the .digest() call. '---------------> HASH”…””}”hjVsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h K´hj7hžhubhÉ)”}”(hŒrHere is a schematic of how the .export()/.import() functions are called when used from another part of the kernel.”h]”hŒrHere is a schematic of how the .export()/.import() functions are called when used from another part of the kernel.”…””}”(hjdhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h KÇhj7hžhubhõ)”}”(hXõKEY--. DATA--. v v ! .update() may not be called .setkey() -> .init() -> .update() -> .export() at all in this scenario. ^ | | '-----' '--> PARTIAL_HASH ----------- other transformations happen here ----------- PARTIAL_HASH--. DATA1--. v v .import -> .update() -> .final() ! .update() may not be called ^ | | at all in this scenario. '----' '--> HASH1 PARTIAL_HASH--. DATA2-. v v .import -> .finup() | '---------------> HASH2”h]”hXõKEY--. DATA--. v v ! .update() may not be called .setkey() -> .init() -> .update() -> .export() at all in this scenario. ^ | | '-----' '--> PARTIAL_HASH ----------- other transformations happen here ----------- PARTIAL_HASH--. DATA1--. v v .import -> .update() -> .final() ! .update() may not be called ^ | | at all in this scenario. '----' '--> HASH1 PARTIAL_HASH--. DATA2-. v v .import -> .finup() | '---------------> HASH2”…””}”hjrsbah}”(h]”h ]”h"]”h$]”h&]”jjuh1hôhŸh¶h KÌhj7hžhubhÉ)”}”(hŒ»Note that it is perfectly legal to "abandon" a request object: - call .init() and then (as many times) .update() - _not_ call any of .final(), .finup() or .export() at any point in future”h]”hŒ¿Note that it is perfectly legal to “abandon†a request object: - call .init() and then (as many times) .update() - _not_ call any of .final(), .finup() or .export() at any point in future”…””}”(hj€hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Kàhj7hžhubhÉ)”}”(hŒãIn other words implementations should mind the resource allocation and clean-up. No resources related to request objects should remain allocated after a call to .init() or .update(), since there might be no chance to free them.”h]”hŒãIn other words implementations should mind the resource allocation and clean-up. No resources related to request objects should remain allocated after a call to .init() or .update(), since there might be no chance to free them.”…””}”(hjŽhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Kähj7hžhubeh}”(h]”Œ5cipher-definition-with-struct-shash-alg-and-ahash-alg”ah ]”h"]”Œ5cipher definition with struct shash_alg and ahash_alg”ah$]”h&]”uh1h¡hjÇhžhhŸh¶h K©ubh¢)”}”(hhh]”(h§)”}”(hŒ-Specifics Of Asynchronous HASH Transformation”h]”hŒ-Specifics Of Asynchronous HASH Transformation”…””}”(hj§hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj¤hžhhŸh¶h KêubhÉ)”}”(hŒ©Some of the drivers will want to use the Generic ScatterWalk in case the implementation needs to be fed separate chunks of the scatterlist which contains the input data.”h]”hŒ©Some of the drivers will want to use the Generic ScatterWalk in case the implementation needs to be fed separate chunks of the scatterlist which contains the input data.”…””}”(hjµhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhŸh¶h Kìhj¤hžhubeh}”(h]”Œ-specifics-of-asynchronous-hash-transformation”ah ]”h"]”Œ-specifics of asynchronous hash transformation”ah$]”h&]”uh1h¡hjÇhžhhŸh¶h Kêubeh}”(h]”Œ hashing-hash”ah ]”h"]”Œhashing [hash]”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K‰ubeh}”(h]”Œdeveloping-cipher-algorithms”ah ]”h"]”Œdeveloping cipher algorithms”ah$]”h&]”uh1h¡hhhžhhŸh¶h Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”h¶uh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(h¦NŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”jþŒerror_encoding”Œutf-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”h¶Œ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(jØjÕjCj@j j Œregistration specifics”NjjjÄjÁj•j’j¼j¹jÐjÍj4j1j¡jžjÈjÅuŒ nametypes”}”(j؉jC‰j ‰jB‰j‰jĉj•‰j¼‰jЉj4‰j¡‰jȉuh}”(jÕh£j@h·j jFj¢jsjj©jÁjjlj=j’jqj¹j˜jÍjÇj1jæjžj7jÅj¤uŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”j Ks…”R”Œparse_messages”]”hŒsystem_message”“”)”}”(hhh]”hÉ)”}”(hŒ9Duplicate implicit target name: "registration specifics".”h]”hŒ=Duplicate implicit target name: “registration specificsâ€.”…””}”(hjfhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÈhjcubah}”(h]”h ]”h"]”h$]”h&]”jlaŒlevel”KŒtype”ŒINFO”Œsource”h¶Œline”Kmuh1jahj=hžhhŸh¶h KmubaŒtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.