java中,Node node = (Node) value; 其中Node是接口,这个语句是啥意思啊?谢谢。

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中,Node node = (Node) value; 其中Node是接口,这个语句是啥意思啊?谢谢。相关的知识,希望对你有一定的参考价值。

java的类型的强制转换,
这里value一般是Node的子类吧(可能是Object类型了表现为),
Node node = (Node) value;强制转换后就可以直接调用Node的方法了。追问

value是Object类型的,那Node的方法是在另外一个类实现的呀,比如是类Test,为什么不是调用Test中的方法,直接调用Node的方法就可以了,Node中不是没实现方法体么?谢谢。

追答

Node是接口或者抽象类,所以没有具体实现方法,虽然value这里是Object的,但是这个value的本质肯定是一个Node的实现类(子类),不然的话,这里强制转换是会出错的。
比如你的Node node = (Node) value;是在如下的方法里
public void showNodeAttr(Object value)
Node node = (Node) value;


但是你调用这个showNodeAttr方法的时候,传入的这个value对象肯定是实现了Node接口的,就像你说的Test类。
比如 Test test = new Test();
showNodeAttr(test);
一般是这么用的。
而且这种调用接口的方式也是java实现多态的主要内容。

参考技术A 面向对象的一条基本准则就是接口隔离原则,就是尽量使用接口作为对象的显示类型。使用接口的好处是当你改变Node的实现类的时候,使用它的地方是不需要改变的。

在 node 中加密并在 java 中解密

【中文标题】在 node 中加密并在 java 中解密【英文标题】:Encrypt in node and decrypt in java 【发布时间】:2013-11-10 23:58:05 【问题描述】:

我有一个 Java 加密代码。我正在尝试将加密部分移植到节点。基本上,node 会使用 crypto 模块进行加密,然后 Java 会进行解密。

这是我在 Java 中进行加密的方法:

protected static String encrypt(String plaintext) 
    final byte[] KEY = 
            0x6d, 0x79, 0x56, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x70,
            0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b
    ;

    try 
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        final SecretKeySpec secretKey = new SecretKeySpec(KEY, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        final String encryptedString = Base64.encodeToString(
            cipher.doFinal(plaintext.getBytes()), Base64.DEFAULT);

        return encryptedString;
     catch (Exception e) 
        return null;
    

这是我在节点中进行加密的方法:

var crypto = require('crypto'),
    key = new Buffer('6d7956657279546f705365637265744b', 'hex'),
    cipher = crypto.createCipher('aes-128-ecb', key),
    chunks = [];

cipher.setAutoPadding(true);
chunks.push(cipher.update(
    new Buffer(JSON.stringify(someKey: "someValue"), 'utf8'),
    null, 'base64'));
chunks.push(cipher.final('base64'));

var encryptedString = chunks.join('');

在 Java 中,我得到字符串 T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=。这得到正确解密。但是,在节点中,我得到al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=,这显然是不同的,因此它不会被正确解密。

我试图寻找和我有同样问题的人,this github issue 是我能找到的最接近的问题。正如该问题中所建议的,我尝试像这样运行 openssl:

$ echo -e '"someKey": "someValue"' | openssl enc -a -e -aes-128-ecb -K "6d7956657279546f705365637265744b"
T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU=

我得到的结果和java产生的结果很接近,但还是不一样:

T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU=  // openssl
T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=  // java
al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=  // node

这让我想到了一个问题,如何让节点输出与我的 java 代码相同的加密字符串?我只能在 node 中更改我的代码,而不能在 java 中更改。

【问题讨论】:

每个使用什么填充格式?你怎么知道被加密的内容在每个平台上实际上是相同的(我认为没有理由假设 Node 的 JSON.stringify 输出与你作为 plaintext 传递给 Java 的任何内容相同)? Java 正在使用 PKCS5Padding。从我读过的内容来看,openssl 也使用相同的(抱歉我丢失了链接)。对于节点,我不确定如何指定填充,这就是我选择使用cipher.setAutoPadding(true) 的原因。编辑:找到链接。查看接受的答案here 两个输入是相同的。当我再次对此进行测试时,我将 JSON.stringify 的输出(手动)传递给 java encrypt,并带有一些转义字符:encrypt("\"someKey\":\"someValue\"") 你需要比较字节数组。相同外观的文本可以用不同字符集的不同字节编码,String#getBytes 显式依赖于平台字符集。转储字节数组。 没有包含数组,java 转储看起来像这样:7b22736f6d654b6579223a22736f6d6556616c7565227d 这与它在 node.js 中的样子相同。可能问题出在其他地方。 【参考方案1】:

我以为我从节点和 java 端发布了一个完整的 CBC 示例(256 而不是 128): 如果您收到 java.security.InvalidKeyException,则必须安装 Java Cryptography Extension (JCE) 无限强度管辖策略文件:

Java 6 link Java 7 link Java 8 link

Java 加密和解密。

    import java.security.MessageDigest;
    import javax.crypto.spec.SecretKeySpec;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.Cipher;
    import java.util.Base64;
    import javax.xml.bind.DatatypeConverter;

    public class AESExample 
        private static byte[] iv = "0000000000000000".getBytes();
        private static String decrypt(String encrypted, String seed)
                throws Exception 
            byte[] keyb = seed.getBytes("utf-8");
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] thedigest = md.digest(keyb);
            SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
            Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            dcipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(seed.getBytes("UTF-8"), "AES"), new IvParameterSpec(iv));
            byte[] clearbyte = dcipher.doFinal(DatatypeConverter
                    .parseHexBinary(encrypted));
            return new String(clearbyte);
        
        public static String encrypt(String content, String key) throws Exception 
            byte[] input = content.getBytes("utf-8");
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] thedigest = md.digest(key.getBytes("utf-8"));
            SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("UTF-8"), "AES"), new IvParameterSpec(iv));
            byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
            int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
            ctLength += cipher.doFinal(cipherText, ctLength);
            return DatatypeConverter.printHexBinary(cipherText);
        

public static String encrypt128(String content, String key) throws Exception 
        byte[] input = content.getBytes("utf-8");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(DatatypeConverter.parseHexBinary(key), "AES"), new IvParameterSpec(iv));
         byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));
        return DatatypeConverter.printHexBinary(encrypted);
    

        public static void main(String[] args) throws Exception 
            String data = "Here is my string";
            String key = "1234567891123456";
            String cipher = AESExample.encrypt(data, key);
            String decipher = AESExample.decrypt(cipher, key);
            System.out.println(cipher);
            System.out.println(decipher);
            System.out.println(AESExample.encrypt(data, "1234567891123456"));
            System.out.println(AESExample.encrypt128(data, "d7900701209d3fbac4e214dfeb5f230f"));
        
    

以下两个方向节点:

    var crypto = require('crypto');
        var iv = new Buffer('0000000000000000');
        // reference to converting between buffers http://nodejs.org/api/buffer.html#buffer_new_buffer_str_encoding
        // reference node crypto api http://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv
        // reference to ECB vs CBC cipher methods http://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher

        var encrypt = function(data, key) 
          var decodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest();
          var cipher = crypto.createCipheriv('aes-256-cbc', decodeKey, iv);
          return cipher.update(data, 'utf8', 'hex') + cipher.final('hex');
        ;

        var decrypt = function(data, key) 
          var encodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest();
          var cipher = crypto.createDecipheriv('aes-256-cbc', encodeKey, iv);
          return cipher.update(data, 'hex', 'utf8') + cipher.final('utf8');
        ;

       var decrypt128 = function(data, key) 

          var encodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest();
         var cipher = crypto.createDecipheriv('aes-128-cbc', new Buffer(key, 'hex'),
    new Buffer(
      iv));
  return cipher.update(data, 'hex', 'utf8') + cipher.final('utf8');
;
        var data = 'Here is my string'
        var key = '1234567891123456';
        var cipher = encrypt(data, key);
        var decipher = decrypt(cipher, key);
        console.log(cipher);
        console.log(decipher);
        // the string below was generated from the "main" in the java side
        console.log(decrypt(
          "79D78BEFC06827B118A2ABC6BD9D544E83F92930144432F22A6909EF18E0FDD1", key));
        console.log(decrypt128(
  "3EB7CF373E108ACA93E85D170C000938A6B3DCCED53A4BFC0F5A18B7DDC02499",
  "d7900701209d3fbac4e214dfeb5f230f"));

【讨论】:

@TerryLennox 有效,但我在您的代码中进行了两次更改之后才有效,所以请编辑它,第一个是您没有使用 java 代码中的 skc encrypt 函数,将hex 更改为base64 后节点代码中的第二个它醒了,非常感谢 bdw 的欢呼。 skc 未在 java 代码中使用。它是否代替 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key. getBytes("UTF-8"), "AES"), new IvParameterSpec(iv)); 应该用吗? 当我使用您的 js 代码加密您的演示字符串时,我得到 fccb0c3810043aa268099a07d694fad3e0561c7b93fbbcfb3868d2200239ae51 并且当我尝试使用您的 java 代码解密时(密钥与您的示例中给出的密钥保持相同,我收到错误:异常在线程“main”中 javax.crypto.BadPaddingException:给定最终块未正确填充。如果在解密期间使用了错误的密钥,则会出现此类问题。 DatatypeConfigurationException: 未找到提供程序 org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl【参考方案2】:

最后,我找到了解决问题的方法。感谢this 家伙。解决方案的关键是初始化向量。引用要点:

// ECB模式不需要IV,所以保持这样就可以了。

解决方案如下所示:

var crypto = require('crypto'),
    iv = new Buffer(''),
    key = new Buffer('6d7956657279546f705365637265744b', 'hex'),
    cipher = cypto.createCipheriv('aes-128-ecb', key, iv),
    chunks = [];

chunks.push(cipher.update(
    new Buffer(JSON.stringify(someKey: "someValue"), 'utf8'),
    'buffer', 'base64'));
chunks.push(cipher.final('base64'));
var encryptedString = chunks.join('');

【讨论】:

这不是真正的问题,问题在于createCipher 使用的密码是 派生 (IV 也是派生的,但被忽略了欧洲央行)。然而,createCipheriv 方法直接使用密钥作为字节。所以解决方案是正确的(+1),但它正确的原因不是:P 那么替代解决方案是什么? 您已经得到了正确的解决方案,如评论中所示。 AFAIK别无选择。 createCiphercreateCipheriv 之间的区别也让我感到困惑(以及在 Java 中 "AES" 表示 ECB 而在 Node/OpenSSL 中 "aes128" 表示 CBC 的事实)。感谢@MaartenBodewes 的提示。 对我来说,使用 createCipherivnew Buffer('') 而不是 createCipher 会产生很大的不同...!【参考方案3】:

在 Node.Js 中加密和在 Java 中解密的工作示例:

加密:

var crypto = require('crypto')
var cipher = crypto.createCipher('aes-128-ecb','somepassword')
var text = "the big brown fox jumped over the fence"
var crypted = cipher.update(text,'utf-8','hex')
crypted += cipher.final('hex')
//now crypted contains the hex representation of the ciphertext

解密:

private static String decrypt(String seed, String encrypted) throws Exception 
    byte[] keyb = seed.getBytes("UTF-8");
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] thedigest = md.digest(keyb);
    SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
    Cipher dcipher = Cipher.getInstance("AES");
    dcipher.init(Cipher.DECRYPT_MODE, skey);

    byte[] clearbyte = dcipher.doFinal(toByte(encrypted));
    return new String(clearbyte);


private static byte[] toByte(String hexString) 
    int len = hexString.length()/2;
    byte[] result = new byte[len];
    for (int i = 0; i < len; i++) 
        result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
    
    return result;

【讨论】:

以上是ECB模式,没有IV向量。【参考方案4】:

重要提示:Matthew Payne 的回答只适用于“在节点中加密并在 java 中解密”而不适用于两者,所以如果你想要两者都不要只是复制和粘贴

【讨论】:

以上是关于java中,Node node = (Node) value; 其中Node是接口,这个语句是啥意思啊?谢谢。的主要内容,如果未能解决你的问题,请参考以下文章

Node服务器对比Java服务器

在 node 中加密并在 java 中解密

Node.js 用户量会不会在一年内超越 Java?

node通过node-java库调用java

Java 中的 org.w3c.dom.Node 和 Node 有啥区别?

Java Script中的Node