emu in blogjava

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  171 随笔 :: 103 文章 :: 1052 评论 :: 2 Trackbacks
今天下午和一个妹子聊到在前端做AES加密,妹子说有一些开源的库,我想webcrypto提出来这么多年,应该主流浏览器很多也应该有原生的支持了吧?写个加测试页面试试看:

<!DOCTYPE html>
<html>
    <head>
        <META NAME="Author" CONTENT="emu">
        <META NAME="Keywords" CONTENT="webcrypto AES-CBC AES-GCM">
    </head>
    <body>
        <div id="out"></div>
        <script type="text/javascript">
            
function output(sign) {
                document.getElementById(
"out").innerHTML += sign + "<br>";
            }
            
function bufferToHex(b){
                
var dataview = new DataView(b);
                result 
= "";
                
for (var i = 0; i < b.byteLength; i += 4) {
                    tmp 
= dataview.getUint32(i).toString(16);
                    result 
+= (tmp.length == 8 ? "" : "0"+ tmp;
                }
                
return result;
            }

            
function bufferToString(b){
                
//new TextDecoder().decode(b)
                var hex=bufferToHex(b);
                
var result=unescape(hex.replace(/(..)/g,"%$1"));
                
return result;
            }
            
function stringToBuffer(s){
                
//new TextEncoder().encode(s);
                 var a = s.split("");
                 
for (var i = 0; i < a.length; i++) {
                        a[i] 
= a[i].charCodeAt(0)
                 };
                 
var result = new Uint8Array(a);
                 
return result;
            }


        
var textToBeEncrypted = 'Hello World!';
        
var bufferToBeEncrypted=stringToBuffer(textToBeEncrypted);
        
var bufferToBeDecrypted;
        
var pwd="let me try this password"
        
var password = stringToBuffer(pwd);
        
var sAlg="AES-CBC";//AES-GCM部分浏览器不支持
        var c = window.crypto || window.msCrypto;
        
var subtle = c.subtle || c.webkitSubtle;
        
var iv = c.getRandomValues(new Uint8Array(16));
        
var alg = { name: sAlg, iv: iv };
        
var op=c.subtle.digest('SHA-256', password)
        
var encryptKey,decryptKey,hash;
        
if(("then" in op)){
            op.then(
function(buffer){
                hash
=buffer;
                c.subtle.importKey('raw', hash, alg, 
false, ['encrypt']).then(function(buffer){
                    encryptKey
=buffer;
                    c.subtle.importKey('raw', hash, alg, 
false, ['decrypt']).then(function(buffer){
                    decryptKey
=buffer;
                    doEncrypt(alg,encryptKey);
                    })
                })
            });
        }
else{
            op.oncomplete
=function(e){
                
var hash=e.target.result;
                
var op=c.subtle.importKey('raw', hash, alg, false, ['encrypt']);
                op.oncomplete
=function(e){
                    encryptKey
=e.target.result;
                    op
=c.subtle.importKey('raw', hash, alg, false, ['decrypt']);
                    op.oncomplete
=function(e){
                        decryptKey
=e.target.result;
                        encryptWithCryptoOperation(alg,encryptKey);
                    }
                }
            }
        }
        
function doEncrypt(alg,encryptKey){
            
var op = c.subtle.encrypt(alg, encryptKey, bufferToBeEncrypted);
            op.then(
function(buffer){
                    bufferToBeDecrypted
=buffer;
                    output(
"pwd: <b><i>"+pwd+"</i></b> alg:<b>"+sAlg+"</b> <br>encrypt("+textToBeEncrypted + ")="+ bufferToHex(buffer));
                    doDecrypt(alg,decryptKey);
                })
        }

        
function doDecrypt(alg,decryptKey){
            
var op = c.subtle.decrypt(alg, decryptKey, bufferToBeDecrypted);
            op.then(
function(buffer){
                output(
"pwd:<b><i>"+pwd+"</i></b>  alg:<b>"+sAlg+"</b> <br>decrypt("+bufferToHex(bufferToBeDecrypted) + ")="+ bufferToString(buffer));
            })
        }

        
function encryptWithCryptoOperation(alg,encryptKey){
            
var op = c.subtle.encrypt(alg, encryptKey);
            op.onerror
=function(e){output(sAlg+"  unsupported")}
            op.process(bufferToBeEncrypted);
            op.oncomplete
=function(e){
                bufferToBeDecrypted
=e.target.result
                    output(
"pwd: <b><i>"+pwd+"</i></b> alg:<b>"+sAlg+"</b> <br>encrypt("+textToBeEncrypted + ")="+ bufferToHex(bufferToBeDecrypted));
                
//decryptWithCryptoOperation(alg,decryptKey)
                setTimeout(decryptWithCryptoOperation,0,alg,decryptKey)
            }
            op.finish();
        }        
        
function decryptWithCryptoOperation  (alg,decryptKey){
            
var op = c.subtle.decrypt(alg, decryptKey);
            op.onerror
=function(e){(sAlg+"  unsupported")}
            op.process(bufferToBeDecrypted);
            op.oncomplete
=function(e){
                
if(!e.target.result){
                    output(
"IE is crazy!<br>");
                    encryptWithCryptoOperation(alg,encryptKey)
                }
else
                    output(
"pwd:<b><i>"+pwd+"</i></b>  alg:<b>"+sAlg+"</b> <br>decrypt("+bufferToHex(bufferToBeDecrypted) + ")="+ bufferToString(e.target.result));
            }
            op.finish();
        }
        
</script>
    </body>
</html>

测试下来感觉各个浏览器支持程度还是参差不齐,IE11和Edge都是不同的实现方式,IE11甚至还会随机出现oncomplete的时候result数据都还没有ready的情况,甚至于有的时候完全相同的入参(包括随机数也相同)加密出来的结果居然会不同,也就是说有的时候加密算法自己会加密错,出来的结果根本就无法被正确解密,实在是个半成品:


(第一次加密错了,第二次加密对了解密错了,第三次终于加解密都对了)


(第一次加密错了,第二次对了)
posted on 2017-06-12 17:48 emu 阅读(1228) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: