由于我们学校的网站太难使用,go 年我决定写一个手机应用程序,以便有更好的用户体验. 我已经使用了JSoup和其他实用程序来制作它.

我发现最近它的使用难度要大得多,网站上有更多的身份验证页面. 我花了一整天的时间来了解如何将代码从JS翻译成Kotlin.


有没有办法让我可以get the ciphertext of the values或者怎么go make the code to be runnable in the Rhino JavaScript evaluator.

encryptBase64的代码是这样的,我不知道how to manage to get the 101 in Kotlin

encryptBase64: function (e) {//e=password
    var r = f();
    var t = s.default.MD5(r);
    console.log("r="+r);//r=GN12MVOFWVZJ51KZ
    console.log("t="+t);//r=GN12MVOFWVZJ51KZ
    console.log("l="+l);//l=c2df1fd689074ff84521cea43a677bbf

    var o = s.default.AES.encrypt(r, l, {iv: l, mode: a, padding: d});
    var n = s.default.AES.encrypt(e, t, {iv: t, mode: a, padding: d});
    console.log("o="+o)//o=tAzMY2LKjgC96ZJHXYjorazfL56s//vgFgoerDmaH3g=
    console.log("n="+n)//n=GQNoFJVGL5qdLyb7KxFXAA==
    var o_cipher=o.ciphertext

    var n_cipher=n.ciphertext
    console.log("o_cipher="+o_cipher)o_cipher=b40ccc6362ca8e00bde992475d88e8adacdf2f9eacfffbe0160a1eac399a1f78
    console.log("n_cipher="+n_cipher)//n_cipher=1903681495462f9a9d2f26fb2b115700
    var i = s.default.lib.WordArray.create([].concat(c(o_cipher.words), c(n_cipher.words)));

    console.log("i="+i)//i=b40ccc6362ca8e00bde992475d88e8adacdf2f9eacfffbe0160a1eac399a1f781903681495462f9a9d2f26fb2b115700
    var stringifiedI=s.default.enc.Base64.stringify(i)
    console.log("stringified i="+stringifiedI)//stringified i=tAzMY2LKjgC96ZJHXYjorazfL56s//vgFgoerDmaH3gZA2gUlUYvmp0vJvsrEVcA
    return stringifiedI
}

我认为ciphertext可能是像AES,而不是RSA或MD5,因为服务器可以解密它没有密钥(我没有发现任何其他东西,但密码加密).

向学校求助是不可能的,我的学校不批准.

完整的代码如下所示(我想大概是CryptoJS): Full Code in GitHub

What have I tried

  • 我试图用Kotlin编写一些代码来执行类似的功能,但它不能正常工作.

我已经创建了一个AES加密/解密扩展函数,如下所示: aes.kt

以及包含callJs()函数的js.kt.

我试着用callJs()来换取结果.

//fun main
    val a= callJs(JS.encryptCode,"aesOene","encryptBase64","password")
    println(a)
object JS{
    val encryptCode: String by lazy {
        val bytes = this::class.java.getResourceAsStream("/aesOene.js")!!.readBytes()
        String(bytes)
    }
}

我得到了这个

Exception in thread "main" org.mozilla.javascript.EcmaError: ReferenceError: "window" is not defined. (aesOene#1)

我try 用这个来实现encryptBase64():

// fun main
    val b=encryptBase64("password")
    println(b)

fun aesKeyBuilder():String{
    val p= arrayListOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")
    val builder=StringBuilder()
    for (t in 0 until 16){
        val o= ceil(35*Math.random()).toInt()
        builder.append(p[o])
    }
    return builder.toString()
}
fun encryptBase64(e:String):String{
    val r=aesKeyBuilder()
    val l="ass-apex".md5
    val t=r.md5
    val o=r.encryptByAES(l,)
    val n=e.encryptByAES(t,)
    val i=o+n
    return i.base64
}

而且它没有得到正确的结果.

What was I expecting

  • 在Kotlin或Java中获得encryptBase64()的结果的方法

推荐答案

为了正确执行,h.encryptBase64()函数需要字数组l,该字数组l或者使用函数h.setSecret(e)被设置为等于密码e的MD5散列,或者可以替代地被直接定义为任何16字节的字数组,例如l = CryptoJS.enc.Utf8.parse('0123456789012345').

然后,h.encryptBase64()函数执行以下操作:

  • 通过函数f()生成由来自p的字符序列组成的随机16字符串r.
  • r生成MD5散列t.
  • r在带有PKCS#7填充的CBC模式下用AES加密(密文o_cipher).l既用于密钥又用于IV.
  • 明文以具有PKCS#7填充的CBC模式用AES加密(密文n_cipher).t同时用于 keys 和IV.
  • 密文o_ciphern_cipher被连接(结果i).
  • i是Base64编码并返回的.

Be aware that the current JavaScript code is unnecessarily complicated and riddled with vulnerabilities (e.g. MD5, Math.Random).
The usual approach would use a reliable key derivation function (at least PBKDF2) in conjunction with a random, non-secret salt to generate a key that would be used to encrypt the plaintext.
The salt would be passed to the decrypting side together with the ciphertext so that the key could be reconstructed.
Actually, it would make sense to revise the JavaScript code before porting, but since you are probably interested in a 1:1 porting of the unchanged code, this is described below:

  • 你发布的aesKeyBuilder()函数原则上可以用作f()的对应函数.但是,Math.random()应该替换为SecureRandom#nextDouble(),因为Math.random()不是加密安全的:

    import java.security.SecureRandom
    ...
    fun aesKeyBuilder(): String {
        val p = arrayListOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")
        val builder = StringBuilder()
        val secureRandom = SecureRandom()
        for (t in 0 until 16){
            val o= ceil(35 * secureRandom.nextDouble()).toInt()
            builder.append(p[o])
        }
        return builder.toString()
    }
    
  • 下一步是定义在CBC模式和PKCS#7填充中使用AES执行加密的函数,例如:

    import javax.crypto.Cipher
    import javax.crypto.spec.IvParameterSpec
    import javax.crypto.spec.SecretKeySpec
    ...
    fun aesEncrypt(key: ByteArray, data: ByteArray): ByteArray {
        val secretKeySpec = SecretKeySpec(key, "AES")
        val ivParameterSpec = IvParameterSpec(key)
        val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
        return cipher.doFinal(data)
    }
    
  • 这样,JavaScript代码的逻辑就可以被移植到Kotlin,如下所示:

    import android.util.Base64
    import java.security.MessageDigest
    ...
    val password = "my passphrase"
    val plaintext = "The quick brown fox jumps over the lazy dog"
    val key_l = MessageDigest.getInstance("MD5").digest(password.toByteArray())
    val key_r = aesKeyBuilder().toByteArray()
    val key_t = MessageDigest.getInstance("MD5").digest(key_r)
    val encKey_o = aesEncrypt(key_l, key_r)
    val ciphertext_n = aesEncrypt(key_t, plaintext.toByteArray())
    val result_i = encKey_o + ciphertext_n
    val resultB64 = Base64.encodeToString(result_i, Base64.NO_WRAP);
    

测试:

对于测试,最好实现一个用于解密的Java代码,该代码对由该代码生成的密文进行解密.如果该JavaScript解密代码还解密由Kotlin代码生成的密文,则可以认为Kotlin代码是兼容的.

下面的JavaScript代码成功地执行了这样的测试:

var a = CryptoJS.mode.CBC, 
    d = CryptoJS.pad.Pkcs7, l = "", u = "",
    p = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"],
    f = function () { 
        return function (e) {
            for (var r = "", t = 0; t < e; t++) {
                var o = Math.ceil(35 * Math.random());
                r += p[o]
            }
            return r
        }(16)
    }, 
    h = { 
        encryptBase64: function (e) {
            var r = f();
            var t = CryptoJS.MD5(r);
            console.log("r="+r);
            console.log("t="+t);
            console.log("l="+l);
                        
            var o = CryptoJS.AES.encrypt(r, l, {iv: l, mode: a, padding: d});
            var n = CryptoJS.AES.encrypt(e, t, {iv: t, mode: a, padding: d});
            console.log("o="+o)
            console.log("n="+n)
            var o_cipher=o.ciphertext
                        
            var n_cipher=n.ciphertext
            console.log("o_cipher="+o_cipher)
            console.log("n_cipher="+n_cipher)
            var i = CryptoJS.lib.WordArray.create([].concat(c(o_cipher.words), c(n_cipher.words)));
                        
            console.log("i="+i)
            var stringifiedI=CryptoJS.enc.Base64.stringify(i)
            console.log("stringified i="+stringifiedI)
            return stringifiedI
        }, 
        setSecret: function (e) {
            u = e, l = CryptoJS.MD5(u)
        }
    };

function c(e) {
    if (Array.isArray(e)) {
        for (var r = 0, t = Array(e.length); r < e.length; r++) t[r] = e[r];
        return t
    }
    return Array.from(e)
}
      
// encryption
h.setSecret('my passphrase') 
var ciphertext = h.encryptBase64('The quick brown fox jumps over the lazy dog')
console.log('Ciphertext:', ciphertext)

// decryption from JavaScript ciphertext
var ciphertextWA = CryptoJS.enc.Base64.parse(ciphertext)
var encryptedKeyWA = CryptoJS.lib.WordArray.create(ciphertextWA.words.slice(0, 256 / 32))
var encryptedDataWA = CryptoJS.lib.WordArray.create(ciphertextWA.words.slice(256 / 32))
var l = CryptoJS.MD5('my passphrase') // apply passphrase from setSecret
var r = CryptoJS.AES.decrypt({ciphertext: encryptedKeyWA}, l, {iv: l, mode: a, padding: d})
var t = CryptoJS.MD5(r)
var e = CryptoJS.AES.decrypt({ciphertext: encryptedDataWA}, t, {iv: t, mode: a, padding: d})
console.log('Decrypted:', e.toString(CryptoJS.enc.Utf8))

// decryption from Kotlin ciphertext 
var ciphertextFromKotlin = 'rFXxMQjsIhfCOPiIbgLTJJioVqb7ONCp9Tx3WoTpbF9QxlJNdpR4r6mPtBbnSsEl9PL30hoER6P+RJS9hVUbs/i7ipxhwqiFEbbH97ryZmM='
var ciphertextWA = CryptoJS.enc.Base64.parse(ciphertextFromKotlin)
var encryptedKeyWA = CryptoJS.lib.WordArray.create(ciphertextWA.words.slice(0, 256 / 32))
var encryptedDataWA = CryptoJS.lib.WordArray.create(ciphertextWA.words.slice(256 / 32))
var l = CryptoJS.MD5('my passphrase') // apply passphrase from Kotlin code
var r = CryptoJS.AES.decrypt({ciphertext: encryptedKeyWA}, l, {iv: l, mode: a, padding: d})
var t = CryptoJS.MD5(r)
var e = CryptoJS.AES.decrypt({ciphertext: encryptedDataWA}, t, {iv: t, mode: a, padding: d})
console.log('Decrypted:', e.toString(CryptoJS.enc.Utf8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js"></script>

Javascript相关问答推荐

被CSS优先级所迷惑

使搜索栏更改语言

使用useEffect,axios和useParams进行react测试

有没有可能使滑动img动画以更快的速度连续?

XSLT处理器未运行

使用ThreeJ渲染的形状具有抖动/模糊的边缘

编辑文本无响应.onClick(扩展脚本)

Reaction Native中的范围滑块

IF语句的计算结果与实际情况相反

Web Crypto API解密失败,RSA-OAEP

未加载css colored颜色 ,无法将div设置为可见和不可见

Reaction Redux&Quot;在派单错误中检测到状态Mutations

如何使用基于promise (非事件emits 器)的方法来传输数据?

使用父标签中的Find函数查找元素

如何使本地html页面在重新加载时保持当前可隐藏部分的打开状态?

Next.js无法从外部本地主机获取图像

无法使用Redux异步函数读取未定义的useEffect钩子的属性';map';

如何设置时间选取器的起始值,仅当它获得焦点时?

material UI自动完成全宽

ReactJS Sweep Line:优化SciChartJS性能,重用wasmContext进行多图表渲染