No, this does not extend AESEngine or CryptixAESEngine.
Field Summary
Modifier and TypeFieldDescriptionprivate final I2PAppContextThe context supplying the random.private final LogLogger for this class.private static final intPayload length a single ElGamal block can carry, in bytes.private static final intLength of one encrypted ElGamal block, in bytes.static final intEnforced since release 0.6.private static final intSmallest possible encrypted result, in bytes.Constructor Summary
ConstructorsConstructorDescriptionCreates engine with given context and initializes crypto frequency stats.Method Summary
Modifier and TypeMethodDescriptionbyte[]decrypt(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) Decrypt the message using the given private key and using tags from the specified key manager.(package private) byte[]decryptAESBlock(byte[] encrypted, int offset, int encryptedLen, SessionKey key, byte[] iv, byte[] sentTag, Set<SessionTag> foundTags, SessionKey foundKey) Decrypt the AES data with the session key and IV.private byte[]decryptExistingSession(byte[] data, SessionKey key, PrivateKey targetPrivateKey, Set<SessionTag> foundTags, SessionKey usedKey, SessionKey foundKey) Scenario 2: The data begins with 32 byte session tag, which also serves as the preIV.byte[]decryptFast(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) Tags only.private byte[]decryptNewSession(byte[] data, PrivateKey targetPrivateKey, Set<SessionTag> foundTags, SessionKey usedKey, SessionKey foundKey) Scenario 1: Begin with 222 bytes, ElG encrypted, containing:byte[]decryptSlow(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) Full ElG only.byte[]encrypt(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, long paddedSize) Encrypt the data to the target using the given key and deliver the specified tags No new session key This is the one called from GarlicMessageBuilder and is the primary entry point.byte[]encrypt(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, SessionKey newKey, long paddedSize) Encrypt the unencrypted data to the target.(package private) final byte[]encryptAESBlock(byte[] data, SessionKey key, byte[] iv, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize) For both scenarios, this method encrypts the AES area using the given key, iv and making sure the resulting data is at least as long as the paddedSize and also mod 16 bytes.private final byte[]encryptAESBlock(byte[] data, SessionKey key, byte[] iv, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize, int prefixBytes) Encrypt the AES area with the given key and IV, reserving the specified number of bytes at the beginning of the result for the session tag prefix.private byte[]encryptExistingSession(byte[] data, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, SessionKey newKey, long paddedSize) Scenario 2: Begin with 32 byte session tag, which also serves as the preIV.private byte[]encryptNewSession(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize) Scenario 1: Begin with 222 bytes, ElG encrypted, containing:private byte[]halfHash(byte[] preIV) Generate the first 16 bytes of the SHA-256 hash of the data.
Field Details
_log
Logger for this class.MIN_ENCRYPTED_SIZE
private static final int MIN_ENCRYPTED_SIZESmallest possible encrypted result, in bytes.- See Also:
_context
The context supplying the random.MAX_TAGS_RECEIVED
ELG_CLEARTEXT_LENGTH
private static final int ELG_CLEARTEXT_LENGTHPayload length a single ElGamal block can carry, in bytes.- See Also:
ELG_ENCRYPTED_LENGTH
private static final int ELG_ENCRYPTED_LENGTHLength of one encrypted ElGamal block, in bytes.- See Also:
Constructor Details
ElGamalAESEngine
Creates engine with given context and initializes crypto frequency stats.- Parameters:
ctx- the application context supplying the log and stat managers
Method Details
decrypt
public byte[] decrypt(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) throws DataFormatException Decrypt the message using the given private key and using tags from the specified key manager. This works according to the ElGamal+AES algorithm in the data structure spec.Warning - use the correct SessionKeyManager. Clients should instantiate their own. Clients using
I2PAppContext.sessionKeyManager()may be correlated with the router, unless you are careful to use different keys.- Parameters:
data- the encrypted data to decrypt, at least 80 bytestargetPrivateKey- the ElGamal private key matching the target's public keykeyManager- the session key manager supplying the tags to try- Returns:
- decrypted data or null on failure
- Throws:
DataFormatException- if the payload cannot be parsed once decrypted
decryptFast
public byte[] decryptFast(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) throws DataFormatException Tags only. For MuxedEngine use only.- Parameters:
data- the encrypted data to decrypt, at least 80 bytestargetPrivateKey- the ElGamal private key matching the target's public keykeyManager- the session key manager supplying the tag to look up- Returns:
- decrypted data or null on failure
- Throws:
DataFormatException- if the payload cannot be parsed once decrypted
decryptSlow
public byte[] decryptSlow(byte[] data, PrivateKey targetPrivateKey, SessionKeyManager keyManager) throws DataFormatException Full ElG only. For MuxedEngine use only.- Parameters:
data- the encrypted data to decrypt, at least 514 bytestargetPrivateKey- the ElGamal private key matching the target's public keykeyManager- the session key manager recording any tags the payload carries- Returns:
- decrypted data or null on failure
- Throws:
DataFormatException- if the payload cannot be parsed once decrypted
decryptNewSession
private byte[] decryptNewSession(byte[] data, PrivateKey targetPrivateKey, Set<SessionTag> foundTags, SessionKey usedKey, SessionKey foundKey) Scenario 1: Begin with 222 bytes, ElG encrypted, containing:- 32 byte SessionKey - 32 byte pre-IV for the AES - 158 bytes of random padding
After encryption, the ElG section is 514 bytes long. Then encrypt with AES using that session key and the first 16 bytes of the SHA256 of the pre-IV, using the decryptAESBlock method & structure.- Parameters:
data- the encrypted message: the ElGamal-encrypted section first, then the AES-encrypted sectiontargetPrivateKey- our private key used to ElGamal-decrypt the session key and pre-IVfoundTags- set which is filled with any sessionTags found during decryptionusedKey- out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success.foundKey- out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption- Returns:
- null if decryption fails
decryptExistingSession
private byte[] decryptExistingSession(byte[] data, SessionKey key, PrivateKey targetPrivateKey, Set<SessionTag> foundTags, SessionKey usedKey, SessionKey foundKey) throws DataFormatException Scenario 2: The data begins with 32 byte session tag, which also serves as the preIV. Then decrypt with AES using that session key and the first 16 bytes of the SHA256 of the pre-IV:- 2 byte integer specifying the # of session tags - that many 32 byte session tags - 4 byte integer specifying data.length - SHA256 of data - 1 byte flag that, if == 1, is followed by a new SessionKey - data - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
If anything doesn't match up in decryption, it falls back to decryptNewSession
- Parameters:
data- the encrypted message, beginning with the 32-byte session tag that also serves as the pre-IVkey- the existing session key to decrypt withtargetPrivateKey- our private key for the decryptNewSession fallback if the existing key failsfoundTags- set which is filled with any sessionTags found during decryptionusedKey- out parameter. Data must be unset when called; usedKey.setData() will be called by this method on success.foundKey- out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption- Returns:
- decrypted data or null on failure
- Throws:
DataFormatException- declared on the method; decryption failures are caught and reported as a null return
decryptAESBlock
byte[] decryptAESBlock(byte[] encrypted, int offset, int encryptedLen, SessionKey key, byte[] iv, byte[] sentTag, Set<SessionTag> foundTags, SessionKey foundKey) Decrypt the AES data with the session key and IV. The result should be:- 2 byte integer specifying the # of session tags - that many 32 byte session tags - 4 byte integer specifying data.length - SHA256 of data - 1 byte flag that, if == 1, is followed by a new SessionKey - data - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
If anything doesn't match up in decryption, return null. Otherwise, return the decrypted data and update the session as necessary. If the sentTag is not null, consume it, but if it is null, record the keys, etc as part of a new session.
- Parameters:
encrypted- the encrypted blockoffset- the offset of the encrypted data in the bufferencryptedLen- the length of the encrypted datakey- the session keyiv- the AES initialization vectorsentTag- the tag sent with this message, or null to create a new sessionfoundTags- set which is filled with any sessionTags found during decryptionfoundKey- out parameter. Data must be unset when called; may be filled with a new sessionKey found during decryption- Returns:
- decrypted data or null on failure
encrypt
public byte[] encrypt(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, SessionKey newKey, long paddedSize) Encrypt the unencrypted data to the target. The total size returned will be no less than the paddedSize parameter, but may be more. This method uses the ElGamal+AES algorithm in the data structure spec.Unused externally, only called by below (i.e. newKey is always null).
- Parameters:
data- the plaintext to encrypttarget- public key to which the data should be encrypted, must be ELGAMAL_2048. May be null if key and currentTag are non-null.key- session key to use during encryptiontagsForDelivery- session tags to be associated with the key (or newKey if specified), or null; 200 max enforced at receivercurrentTag- sessionTag to use, or null if it should use ElG (i.e. new session)newKey- key to be delivered to the target, with which the tagsForDelivery should be associated, or nullpaddedSize- minimum size in bytes of the body after padding it (if less than the body's real size, no bytes are appended but the body is not truncated)- Returns:
- the encrypted data, at least paddedSize bytes and up to 514 bytes larger
- Throws:
IllegalArgumentException- on bad target EncType
encrypt
public byte[] encrypt(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, long paddedSize) Encrypt the data to the target using the given key and deliver the specified tags No new session key This is the one called from GarlicMessageBuilder and is the primary entry point.Re: padded size: The AES block adds at least 39 bytes of overhead to the data, and that is included in the minimum size calculation.
In the router, we always use garlic messages. A garlic message with a single clove and zero data is about 84 bytes, so that's 123 bytes minimum. So any paddingSize <= 128 is a no-op as every message will be at least 128 bytes (Streaming, if used, adds more overhead).
Outside the router, with a client using its own message format, the minimum size is 48, so any paddingSize <= 48 is a no-op.
Not included in the minimum is a 32-byte session tag for an existing session, or a 514-byte ElGamal block and several 32-byte session tags for a new session. So the returned encrypted data will be at least 32 bytes larger than paddedSize.
- Parameters:
data- the plaintext to encrypttarget- public key to which the data should be encrypted, must be ELGAMAL_2048. May be null if key and currentTag are non-null.key- session key to use during encryptiontagsForDelivery- session tags to be associated with the key or null; 200 max enforced at receivercurrentTag- sessionTag to use, or null if it should use ElG (i.e. new session)paddedSize- minimum size in bytes of the body after padding it (if less than the body's real size, no bytes are appended but the body is not truncated)- Returns:
- the encrypted data, at least paddedSize bytes and up to 514 bytes larger
- Throws:
IllegalArgumentException- on bad target EncType
encryptNewSession
private byte[] encryptNewSession(byte[] data, PublicKey target, SessionKey key, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize) Scenario 1: Begin with 222 bytes, ElG encrypted, containing:- 32 byte SessionKey - 32 byte pre-IV for the AES - 158 bytes of random padding
After encryption, the ElG section is 514 bytes long. Then encrypt the following with AES using that session key and the first 16 bytes of the SHA256 of the pre-IV:- 2 byte integer specifying the # of session tags - that many 32 byte session tags - 4 byte integer specifying data.length - SHA256 of data - 1 byte flag that, if == 1, is followed by a new SessionKey - data - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
- Parameters:
data- the plaintext to encrypt into the AES sectiontarget- public key of the recipient, must be ELGAMAL_2048key- the new session key, delivered to the target in the ElGamal section and used for the AES sectiontagsForDelivery- session tags to be associated with the key or null; 200 max enforced at receivernewKey- a further session key to deliver to the target, or null for no rekey blockpaddedSize- minimum size in bytes of the AES section after padding it- Returns:
- the 514-byte ElGamal section followed by the encrypted AES section
encryptExistingSession
private byte[] encryptExistingSession(byte[] data, SessionKey key, Set<SessionTag> tagsForDelivery, SessionTag currentTag, SessionKey newKey, long paddedSize) Scenario 2: Begin with 32 byte session tag, which also serves as the preIV. Then encrypt with AES using that session key and the first 16 bytes of the SHA256 of the pre-IV:- 2 byte integer specifying the # of session tags - that many 32 byte session tags - 4 byte integer specifying data.length - SHA256 of data - 1 byte flag that, if == 1, is followed by a new SessionKey - data - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
- Parameters:
data- the plaintext to encrypt into the AES sectionkey- the existing session key used for the AES sectiontagsForDelivery- session tags to be associated with the key or null; 200 max enforced at receivercurrentTag- the session tag identifying the existing session, also used as the pre-IVnewKey- a new session key to deliver to the target, or null for no rekey blockpaddedSize- minimum size in bytes of the AES section after padding it- Returns:
- the encrypted AES section with the 32-byte session tag copied over the reserved prefix
halfHash
private byte[] halfHash(byte[] preIV) Generate the first 16 bytes of the SHA-256 hash of the data.Here we are careful to use the SHA256Generator method that does not generate a Hash object or cache the result.
- Parameters:
preIV- the 32 byte pre-IV to hash, from the byte cache; the caller should callSimpleByteCache.release(byte[])on it after use- Returns:
- a 16 byte array from the byte cache; the caller should call
SimpleByteCache.release(byte[])on it after use
encryptAESBlock
final byte[] encryptAESBlock(byte[] data, SessionKey key, byte[] iv, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize) For both scenarios, this method encrypts the AES area using the given key, iv and making sure the resulting data is at least as long as the paddedSize and also mod 16 bytes. The contents of the encrypted data is:- 2 byte integer specifying the # of session tags - that many 32 byte session tags - 4 byte integer specifying data.length - SHA256 of data - 1 byte flag that, if == 1, is followed by a new SessionKey - data - random bytes, padding the total size to greater than paddedSize with a mod 16 = 0
Note: package private for
ElGamalTest.testAES()- Parameters:
data- the plaintext to encrypt into the AES areakey- the AES session key to encrypt withiv- the 16 byte AES initialization vectortagsForDelivery- session tags to be associated with the key or null; 200 max enforced at receivernewKey- key to deliver to the target, or null for no new key blockpaddedSize- minimum size in bytes of the AES area after padding- Returns:
- the encrypted AES area, or null on encryption failure
encryptAESBlock
private final byte[] encryptAESBlock(byte[] data, SessionKey key, byte[] iv, Set<SessionTag> tagsForDelivery, SessionKey newKey, long paddedSize, int prefixBytes) Encrypt the AES area with the given key and IV, reserving the specified number of bytes at the beginning of the result for the session tag prefix.- Parameters:
data- the plaintext to encrypt into the AES areakey- the AES session key to encrypt withiv- the 16 byte AES initialization vectortagsForDelivery- session tags to be associated with the key or null; 200 max enforced at receivernewKey- key to deliver to the target, or null for no new key blockpaddedSize- minimum size in bytes of the AES area after paddingprefixBytes- number of bytes reserved unwritten at the start of the result for the caller to prepend the session tag, 0 if none- Returns:
- the encrypted AES area, preceded by prefixBytes unwritten bytes