| 8 | |
| 9 | // AES(CFB) Encrypt |
| 10 | public final class Encrypt2 implements Codec { |
| 11 | static final int BLOCK_SIZE = 16; |
| 12 | static final @NotNull MethodHandle mhCryptCtor; |
| 13 | static final @NotNull MethodHandle mhCryptInit; |
| 14 | static final @NotNull MethodHandle mhCryptEncrypt; |
| 15 | |
| 16 | private final @NotNull Object aesCrypt; |
| 17 | private final byte[] out = new byte[BLOCK_SIZE]; |
| 18 | private Codec sink; |
| 19 | private int sinkIndex; |
| 20 | private int writeIndex; |
| 21 | |
| 22 | static { |
| 23 | try { |
| 24 | var clsAESCrypt = Class.forName("com.sun.crypto.provider.AESCrypt"); |
| 25 | var cryptCtor = clsAESCrypt.getDeclaredConstructor((Class<?>[])null); |
| 26 | var mCryptInit = clsAESCrypt.getDeclaredMethod("init", boolean.class, String.class, byte[].class); |
| 27 | var mCryptEncrypt = clsAESCrypt.getDeclaredMethod("encryptBlock", |
| 28 | byte[].class, int.class, byte[].class, int.class); |
| 29 | Json.setAccessible(cryptCtor); |
| 30 | Json.setAccessible(mCryptInit); |
| 31 | Json.setAccessible(mCryptEncrypt); |
| 32 | var lookup = MethodHandles.lookup(); |
| 33 | mhCryptCtor = lookup.unreflectConstructor(cryptCtor); |
| 34 | mhCryptInit = lookup.unreflect(mCryptInit); |
| 35 | mhCryptEncrypt = lookup.unreflect(mCryptEncrypt); |
| 36 | } catch (ReflectiveOperationException e) { |
| 37 | throw new ExceptionInInitializerError(e); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * @param sink 如果为null,则需要reset才能开始加密 |
| 43 | * @param key 长度只支持16,24,32字节. 不能为null |
| 44 | * @param iv 长度必须至少BLOCK_SIZE. 如果为null,则需要reset才能开始加密 |
| 45 | */ |
| 46 | public Encrypt2(@Nullable Codec sink, byte @NotNull [] key, byte @Nullable [] iv) throws CodecException { |
| 47 | this.sink = sink; |
| 48 | try { |
| 49 | aesCrypt = mhCryptCtor.invoke(); |
| 50 | mhCryptInit.invoke(aesCrypt, false, "AES", key); |
| 51 | if (iv != null) { |
| 52 | System.arraycopy(iv, 0, out, 0, BLOCK_SIZE); |
| 53 | mhCryptEncrypt.invoke(aesCrypt, out, 0, out, 0); |
| 54 | } |
| 55 | } catch (Error e) { |
| 56 | throw e; |
| 57 | } catch (Throwable e) { // MethodHandle.invoke |
| 58 | throw new CodecException(e); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | /** |
| 63 | * @param sink 不能为null |
| 64 | * @param iv 长度必须至少BLOCK_SIZE. 不能为null |
| 65 | */ |
| 66 | public void reset(@NotNull Codec sink, byte @NotNull [] iv) { |
| 67 | System.arraycopy(iv, 0, out, 0, BLOCK_SIZE); |
nothing calls this directly
no test coverage detected