C# - 尝试使用导入方法从.p8文件创建CngKey,抛出错误“编码或解码操作期间发生错误”。

时间:2017-10-30 22:49:27

标签: c# jwt cng

我正在尝试使用 /* route handling for submission to SIGNUP page */ // this is all just front end validation, with no relation to the database. I think flash messages use that router.post('/signup/users', (req, res, next) => { req.checkBody('username', 'Username field cannot be empty.').notEmpty() req.checkBody('username', 'Username must be between 4-30 characters long.').len(4, 30) req.checkBody('email', 'The email you entered is invalid, please try again.').isEmail() req.checkBody('email', 'Email address must be between 4-100 characters long, please try again.').len(4, 100) req.checkBody('password', 'Password must be between 8-100 characters long.').len(8, 100) // req.checkBody('password', 'Password must include one lowercase character, one uppercase character, a number, and a special character.').matches(/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.* )(?=.*[^a-zA-Z0-9]).{8,}$/, 'i') req.checkBody('passwordMatch', 'Password must be between 8-100 characters long.').len(8, 100) req.checkBody('passwordMatch', 'Passwords do not match, please try again.').equals(req.body.password) // Additional validation to ensure username is alphanumeric with underscores and dashes req.checkBody('username', 'Username can only contain letters, numbers, or underscores.').matches(/^[A-Za-z0-9_-]+$/, 'i') const errors = req.validationErrors() if(errors || flashMessages.error) { res.render('signup', { errors: errors, showErrors: true, signupErrors: flashMessages.error }) } else { let password = req.body.password bcrypt.hash(password, saltRounds, (err, hash) => { user = new User() user.username = req.body.username user.email = req.body.email user.password = hash // PROBLEM STARTS HERE user.save((err, result) => { if(err) { // add flash message here to let user know something was wrong! const flashMessages = res.locals.getMessages() console.log('flash', flashMessages) console.log("Your error: ", err.message) if (err.message.indexOf("duplicate key error") > -1) { req.flash('signupErrors', "Username already in use.") console.log(req.flash("hi")) res.redirect('/signup') console.log("Made it down here.") } else { req.flash('signupErrors', "There was a problem with your registration.") console.log("Made it wayyyyyy down here.") res.redirect('/signup') } // AND ENDS HERE } else { User.find({}).sort({ _id:-1 }).limit(1) .exec((err, newuser) => { if (err) { console.log(err) } else { // logins user through passport function req.login(newuser[0], (err) => { if (err) { console.log("Login error 1: " + err) console.log("Login error 2: " + newuser[0]) console.log("Login error 3: " + newuser[0]._id) } else { console.log("Login sucess BULK: " + newuser[0]) console.log("Login success ._id: " + newuser[0]._id) res.redirect('/home') } }) } }) .catch(next) } }) }) } }) /* route handling for submission to LOGIN page */ router.post('/login/users', passport.authenticate('local', { successRedirect: '/profile', failureRedirect: '/login', failureFlash: true })) 生成JWT令牌(请参阅https://github.com/dvsekhvalnov/jose-jwt)以与Apple的基于令牌的新APN系统配合使用。

JWT编码方法要求secretKey采用Jose.JWT.encode(payload, secretKey, JwsAlgorithm.ES256, header)格式。 这是我的代码将.p8文件从Apple转换为CngKey对象:

CngKey

但是,在最后一行,将引发以下错误。

        var privateKeyContent = System.IO.File.ReadAllText(authKeyPath);
        var privateKey = privateKeyContent.Split('\n')[1];

        //convert the private key to CngKey object and generate JWT

        var secretKeyFile = Convert.FromBase64String(privateKey);
        var secretKey = CngKey.Import(secretKeyFile, CngKeyBlobFormat.Pkcs8PrivateBlob);

输入的格式不正确,因为有一个单独的错误(当我更改blob类型时出现)。

此代码在.NET WebApi v4.6中运行。

我搜索过高和低,但无法解读此错误所指的内容。任何帮助将不胜感激。谢谢。

3 个答案:

答案 0 :(得分:1)

原因我正在使用的.p8文件由于某种原因在其中间有换行符。记事本可能添加了它(并保存了吗?)。我按分界线拆分获取私钥,因此它截断了密钥。一旦我删除了换行符,它就可以正常工作。

如果收到error occurred during encode or decode operation错误,请检查您的.p8(或其他)私钥是否格式错误且长度合适。

答案 1 :(得分:1)

我遇到了同样的问题。我用这个:

var privateKey = privateKeyContent.Split('\n')[1];

然后我分析从Apple下载的令牌文件。我发现文件中有更多\n。我不确定这种格式在哪里不同或苹果改变了。 然后我使用以下代码加载令牌,工作。 实际上,我们可以直接使用这个令牌字符串。

var privateKeyContent = System.IO.File.ReadAllText(authKeyPath);
var privateKeyList = privateKeyContent.Split('\n');
int upperIndex = privateKeyList.Length;
StringBuilder sb = new StringBuilder();
for(int i= 1; i< upperIndex - 1; i++ )
{
    sb.Append(privateKeyList[i]);
    Debug.WriteLine(privateKeyList[i]);
}

答案 2 :(得分:1)

Apple为DeviceCheck提供的安全密钥(p8)也包含换行符。我使用以下代码来获取有效的CngKey:

var privateKeyContent = File.ReadAllText("pathToApplePrivateKey.p8");
var privateKeyList = privateKeyContent.Split('\n').ToList();
var privateKey = privateKeyList.Where((s, i) => i != 0 && i != privateKeyList.Count - 1)
                                   .Aggregate((agg, s) => agg + s);

CngKey key = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);